资源监听器
Eclipse插件实现资源监听的主要方式是实现资源监听器,通过资源监听器,插件就能够保证Workspace中的资源和模型同步。另外,资源监听器还能知道当前什么资源被改变,以及怎样被改变了。
资源监听器要实现IResourceChangeListener接口,并能通过IWorkspace的addResourceChange Listener方法注册。当不再需要资源监听器时,一定要调用removeResourceChangeListener方法把监听器从IWorkspace中删除。
IResourceChangeListener接口的定义如例程1所示。
例程1 IResourceChangeListener.java
package org.eclipse.core.resources;
import java.util.EventListener;
public interface IResourceChangeListener extends EventListener {
public void resourceChanged(IResourceChangeEvent event);
}
IResourceChangeListener接口中只定义resourceChanged方法,当资源改变后,将会执行IResourceChangeListener实例的resourceChanged方法。实现IResourceChangeListener接口如下代码所示。
IResourceChangeListener listener = new IResourceChangeListener() {
public void resourceChanged(IResourceChangeEvent event) {
System.out.println("Something changed!");
}
};
上例实现了一个简单的资源监听器,其中IResourceChangeEvent表示资源改变的事件的对象,通过IResourceChangeEvent,用户获得资源改变的对象,例如“event.getDelta();”。实现资源监听器后,用户要负责把监听器注册到Workspace中,最后还应该删除注册的监听器,步骤如下。
(1)获得Workspace的实例,例如“IWorkspace workspace = ResourcesPlugin.get Workspace();”。
(2)注册资源监听器,例如“workspace.addResourceChangeListener(listener);”。
(3)删除资源监听器,例如“workspace.removeResourceChangeListener(listener);”。
资源访问器
在Workspace中,资源是以树型结构组织的,用户可以通过树型结构访问被改变的资源树。通常,用户应该实现IResourceDeltaVisitor接口,以实现改变资源的访问。IResourceDeltaVisitor接口定义如例程2所示。
例程2 IResourceDeltaVisitor.java
package org.eclipse.core.resources;
import org.eclipse.core.runtime.CoreException;
public interface IResourceDeltaVisitor {
public boolean visit(IResourceDelta delta) throws CoreException;
}
IResourceDeltaVisitor接口只定义visit方法,其中参数IResourceDelta表示Workspace中资源树的改变对象。IResourceDeltaVisitor的实现类只要实现visit方法即可,如例程3所示。
例程3 Visitor.java
class Visitor implements IResourceDeltaVisitor {
public boolean visit(IResourceDelta delta) {
switch (delta.getKind()) {
case IResourceDelta.ADDED :
break;
case IResourceDelta.REMOVED :
break;
case IResourceDelta.CHANGED :
break;
}
return true;
}
}
IResourceDelta有一些整型的常量,指明了当前被改变资源的状态,例如“ADDED、NO_CHANGE、REMOVED”等,IResourceDelta有一个实现类ResourceDelta,通过ResourceDelta的accept方法,结合IResourceDeltaVisitor的实现类,共同实现了Visit设计模式。accept方法的实现如以下代码片段所示。
public void accept(IResourceDeltaVisitor visitor) throws CoreException {
accept(visitor, 0);
}
public void accept(IResourceDeltaVisitor visitor, int memberFlags)
throws CoreException {
final boolean includePhantoms = (memberFlags & IContainer.INCLUDE_PHANTOMS) != 0;
final boolean includeTeamPrivate =
(memberFlags & IContainer.INCLUDE_TEAM_PRIVATE_MEMBERS) != 0;
int mask = includePhantoms ? ALL_WITH_PHANTOMS : REMOVED | ADDED | CHANGED;
if ((getKind() & mask) == 0)
return;
if (!visitor.visit(this))
return;
for (int i = 0; i < children.length; i++) {
ResourceDelta childDelta = children[i];
if (!includeTeamPrivate && childDelta.isTeamPrivate())
continue;
if (!includePhantoms && childDelta.isPhantom())
continue;
childDelta.accept(visitor, memberFlags);
}
}
如以上代码所示,ResourceDelta和IResourceDeltaVisitor的实现类结合起来,实现了Visitor设计模式。Eclipse中还使用了很多的设计模式,实现了Eclipse中很多核心的功能,有兴趣的读者可以先参考设计模式的实现,然后查找Eclipse中的实现,相信更有助于读者进一步理解设计模式的实现,而且对理解Eclipse核心的实现是非常有帮助的。
资源监听的实现
要实现资源监听器,并根据资源改变的内容处理资源改变事件,用户应该先实现IResourceChangeListener接口,并把监听器注册到Workspace中。另外,可以通过实现IResourceDeltaVisitor接口,访问修改的内容,如例程4所示。
例程4 DocIndexUpdater.java
public class DocIndexUpdater implements IResourceChangeListener {
//显示列表
private TableViewer table;
private static final IPath DOC_PATH = new Path("MyProject/doc");
//响应资源改变事件
public void resourceChanged(IResourceChangeEvent event) {
//处理POST_CHANGE事件
if (event.getType() != IResourceChangeEvent.POST_CHANGE)
return;
//获得改变的对象
IResourceDelta rootDelta = event.getDelta();
IResourceDelta docDelta = rootDelta.findMember(DOC_PATH);
if (docDelta == null)
return;
//创建改变的列表
final ArrayList changed = new ArrayList();
IResourceDeltaVisitor visitor = new IResourceDeltaVisitor() {
public boolean visit(IResourceDelta delta) {
//处理IResourceDelta.CHANGED事件
if (delta.getKind() != IResourceDelta.CHANGED)
return true;
if ((delta.getFlags() & IResourceDelta.CONTENT) == 0)
return true;
IResource resource = delta.getResource();
//只处理扩展名为txt的文件
if (resource.getType() == IResource.FILE &&
"txt".equalsIgnoreCase(resource.getFileExtension())) {
//把改变的内容添加到列表
changed.add(resource);
}
return true;
}
};
try {
//通过Visitor模式,遍历docDelta
docDelta.accept(visitor);
} catch (CoreException e) {
}
if (changed.size() == 0)
return;
//显示在table中
Display display = table.getControl().getDisplay();
if (!display.isDisposed()) {
display.asyncExec(new Runnable() {
public void run() {
//确认table是否存在
if (table.getControl().isDisposed())
return;
table.update(changed.toArray(), null);
}
});
}
}
}
如上代码实现了资源监听器,当资源为txt文件时,把文件显示在table中,用户可以通过监听器找到被改变的资源。
提示:Eclipse框架还支持很多其他监听器的实现,例如“IPartListener”,在此无法介绍全面,读者可以查找Eclipse源代码,一定能找到相关代码的实现。