23.4 处理工作空间资源更改事件
工作空间API允许工具对它所感兴趣的资源更改事件进行注册。您可以使用资源更改侦听器来对事件作出响应或执行相应动作,甚至自动执行某些任务。例如,资源更改侦听器可以用于管理Bookmarks视图中的条目。从资源中添加或删除书签标记将触发一次资源更改事件。Bookmarks视图则侦听到该事件,并且判断是否需要对它作出响应。并不是所有的事件发生都要求Bookmarks视图作出相应的更改。而是Bookmarks视图所使用的资源更改侦听器可以快速地判断是否有书签标记发生更改,如果需要,作出相应的反应。用户可以看到视图对更改作出的即时反应(为了测试,您可以打开Bookmarks视图,然后向一个文件中添加一个或两个书签)。
23.4.1 使用工作空间API跟踪更改
可以使用IWorkspace.addResourceChangeListener(...)方法将资源更改侦听器添加到工作空间中。该方法允许您的侦听器接收来自于更改事件的通知,这些更改事件包括:
● 添加、修改、移动或删除文件。
● 打开或关闭项目。
● 添加或删除标记。
● 构建器事件即将启动或已完成。
表23-3中所列的接口用于实现对资源更改侦听器的支持,包括支持创建资源更改侦听器、处理接收到的事件以及访问与资源相关联的资源变化(resource delta)。侦听器是实现IResourceChangeListener接口的一个类,其中定义了resourceChanged方法。该方法可以通过传入的IResourceChangeEvent参数查询事件的类型。适当的时候,侦听器可以获得一个IResourceDelta对象,该对象包含更改受事件影响的资源的细节。
表23-3 资源更改事件接口
|
资源处理接口 |
描 述 |
|
IResourceChangeListener |
如果您希望当发生资源更改事件时收到消息,必须实现该接口。当工作空间中资源发生更改时,将会通知资源更改侦听器 |
|
IResourceChangeEvent |
资源更改事件描述资源所发生的更改。一旦您注册表示对资源更改进行侦听,需要的时候,就会把资源更改事件传递给您 |
|
IResourceDelta |
资源变化代表了资源树的状态在不同的两个时间点之间所发生的更改。一个资源更改事件包含一个资源变化。该资源变化可以使用访问者模式进行处理 |
|
IResourceDeltaVisitor |
为了成为资源变化的访问者,您的类必须实现该接口。访问者模式允许您处理资源变化中的每一项 |
某些事件类型包含一个IResourceDelta对象,该对象包含了事件所引起的更改的信息。
我们可以在插件启动的过程中添加资源更改侦听器,但它只能侦听到发生在添加操作之后的资源更改事件。下面的图23-5显示了在Eclipse的一次启动和关闭生命周期内,所发生的更改事件集(A、B、C、D和E)。
默认情况下,除了对资源属性的操作之外,每一次对资源的更改操作,都会被识别为一次事件,并会被通知给对此感兴趣的资源更改侦听器。正如您可能想象的那样,如果存在大量的更改事件和多个资源侦听器,事件的处理过程将会成为一个性能瓶颈。减少事件的发生次数,则是导致更改事件发生的那段代码的职责。使用IWorkspaceRunnable接口来减少事件发生次数的技术将在本章后续部分的“资源更改事件管理”一节中讨论。

图23-5 带有一个资源更改侦听器的事件处理过程
一般情况下,用户在使用Eclipse时并不会启动插件,直到有需要时,才会启动。在插件的启动过程中,它可以向工作空间添加资源更改事件。只有那些发生在侦听器添加之后的事件,插件才会收到通知,因此,正如图23-5所示,资源更改侦听器只会收到资源更改事件D和E的通知。
23.4.2 添加资源更改侦听器
您可以使用下面任何一种方法向工作空间添加资源更改侦听器,之后,您将会收到所侦听的更改事件的通知。
addResourceChangeListener(
IResourceChangeListener 1istener)
addResourceChangeListener(
IResourceChangeListener listener, int eventMask)
第一种方法是添加一个基本的侦听器,它将收到发生的所有非构建的资源更改事件(关闭、删除和更改)。第二种方法则允许您在添加侦听器时使用一个事件屏蔽参数,以选择发送到侦听器的资源更改事件类型。通过这种方法,您可以过滤掉任何您认为不需要处理的事件。表23-4列出了各种可以发送到侦听器的资源更改事件类型。
表23-4 资源更改事件类型
|
更 改 事 件 |
工作空间 |
有无资源变化 |
描 述 |
|
PRE_CLOSE |
锁定 |
无 |
通知侦听器,项目即将关闭。对于每个打开的项目,在关闭工作空间的过程中也会触发该事件 |
|
PRE_DELETE |
锁定 |
无 |
通知侦听器,项目即将删除 |
|
PRE_BUILD |
不锁定 |
有 |
在发生任何自动构建之前通知侦听器。当Eclipse平台检测到需要进行自动构建时,就会广播此事件,而不管实际上是否启用了自动构建功能 |
|
POST_BUILD |
不锁定 |
有 |
在发生任何自动构建后通知侦听器。在Eclipse平台执行自动构建后广播此事件,而不管实际上是否启用了自动构建功能 |
|
POST_CHANGE |
锁定 |
有 |
向侦听器通知一次资源更改事件。在POST_BUILD事件通知完成之后,将广播该事件通知。资源变化包含任何由构建器在自动构建过程中产生的更改 |
PRE_CLOSE和PRE_DELETE事件只是表示项目的状态而非事件的历史情况。这两种类型的事件对于触发清除操作非常有用,例如删除项目资源在内存中或状态目录中的表示。只有PRE_BUILD和POST_BUILD事件允许您的侦听器在通知周期内创建或者修改资源。这使得不同工具定义的所有POST_CHANGE事件侦听器都有机会对同一资源变化作出反应。
下面的代码示例,说明了如何查询资源更改事件信息以及如何获取资源变化以便进一步处理。
public void resourceChanged(IResourceChangeEvent event) {
switch (event.GetType()) {
case IResourceChangeEvent.PRE_CLOSE :
System.out.print1n(
"Closing: " + event.getResource().getFullPath());
break;
case IResourceChangeEvent.PRE_DELETE :
System.out.println(
"Deleting : " + event.getResource().getFullPath());
break;
case IResourceChangeEvent.PRE_AUTO_BUILD :
System.out.print1n(" -> Auto build about to run.");
break;
case IResourceChangeEvent.POST_AUTO_BUILD :
System.out.println(
" -> Auto build complete, visiting the delta...");
try {
event.getDelta().accept(
new Simp1eResourceDe1taVisitor());
} catch (CoreException e) {
System.out.println(e);
}
break;
case IResourceChangeEvent.POST_CHANGE :
System.out.print1n(
" -> Resource(s) changed, visiting the delta...");
try {
event.getDelta().accept(
new SimpleResourceDeltaVisitor());
} catch (CoreException e) {
System.out.println(e);
}
}
}
该段代码也展示了,当事件提供了一个资源变化时(仅POST_事件),如何从传递给资源更改侦听器的事件中获取资源变化。如上所示,event.getDelta方法可以用于获取一个IResourceDelta对象的引用。除此之外,还需要一个访问者来查找资源变化中所标识的更改。
您也可以直接访问资源变化以确定是否是您所感兴趣的资源发生了更改。这种方式允许您基于路径来查询资源变化:
event.getDelta().findMember(IPath);
相对于访问整个资源变化树的方法,该方法更加高效,但是您必须拥有一个您所感兴趣的具体文件或文件夹,以便进行查询。






