Resource Change listener
Interface:Iresourcechangelistener
IWorkspace workspace = ResourcesPlugin.getWorkspace(); IResourceChangeListener listener = new IResourceChangeListener() { public void resourceChanged(IResourceChangeEvent event) { System.out.println("Something changed!"); } }; workspace.addResourceChangeListener(listener); //... some time later one ... workspace.removeResourceChangeListener(listener);
During the notification of resource changes, the workspace will
Locked to avoid generating more notifications.
Resource API
Resource API is being executed
Creating, copying, moving, and deleting
Resource change events are broadcasted externally during operations.
Resource Operations are nested. For example, the ifile. Move operation triggers
The ifile. Create operation creates a new file, and then triggers an ifile. Delete
Delete old files. Therefore, an ifile. Move operation is nested with
Ifile. Create operation and one
Ifile. delete operation,However, the preceding operations are only notified once..
Batching changes
When a batch of resource change events need to be notified, batching is required to improve performance. This ensures that only one resource change event is broadcast, rather than multiple events.
IWorkspace workspace = ResourcesPlugin.getWorkspace(); final IProject project = workspace.getRoot().getProject("My Project"); IWorkspaceRunnable operation = new IWorkspaceRunnable() { public void run(IProgressMonitor monitor) throws CoreException { int fileCount = 10; project.create(null); project.open(null); for (int i = 0; i < fileCount; i++) { IFile file = project.getFile("File" + i); file.create(null, IResource.NONE, null); } } }; workspace.run(operation, null);
Eclipse 3.0 does not guarantee that iworkspacerunnable will prevent other notifications during execution. The reason for this is to ensure that the corresponding user events of the UI can be made during the notification.
Eclipse 3.0 introduces a new type of workspacejob, which can put a large number of workspace resource change operations in a job for execution in the background.
A more powerful feature when the resource is changed outside the workspace resourcechangelistener will also be notified, such as directly making changes to the file system files. Because most operating systems do not have such a mechanism, after the iresource. refreshlocal operation is executed, all listener will be notified of resource changes.
Iresourcechangeevent
LEvent Type
Pre_change, post_change, pre_build, post_build, pre_close, post_close, pre_delete, post_delete
LIresourcedelta
Iresourcedelta. getkind ()
Iresourcedelta. Added
Iresourcedelta. removed
Iresourcedelta. Changed
Iresourcedelta. getflags ()
Iresourcedelta. Content
Iresourcedelta. Replaced
Iresourcedelta. removed
Iresourcedelta. moved_from
Iresourcedelta. getmovedfrompath ()
Iresourcedelta. moved_to
Iresourcedelta. getmovedtopath ()
Iresourcedelta. Markers
(Imarkerdelta [] markers = delta. getmarkerdeltas ())
Listener Performance
Resource Change listener must be lightweight and can be executed quickly. Resource change notifications are often sent. If the performance of listener is not high, the performance of the entire platform will be affected. If there is a lot of work to be done in listener, it is best to put it in the background thread for execution.
Iresourcedelta. findmember (ipath) can be used to quickly locate the iresourcedelta we are interested in, without having to send down notifications in a tree structure.
Iresourcedelta. Accept (iresourcedeltavistor) to access the branches of the resourcedeltavistor tree that we care about.
Thread security issues: We cannot control the thread in which our listener will be executed. Workspace operations will appear in any thread, Resource
Change listener will also run in any thread that triggers this operation. If we want our update operations to appear in a specific thread, we have to ensure that the Code is post to that thread. Usually we need to update the user interface, first obtain the UI Display object, using the display. syncexec () or display. asyncexec () method.
If asynchronous execution is used, note that resourcedelta has an "expire date ". if an iresourcedelta is passed to another thread, if the listener resourcechanged () method has been returned in another thread, an error will occur when referencing iresourcedelta. Make sure that the listener does not keep saving the resource
Delta references, because the number of resource Delta is large. If you keep referencing it, it will lead to memory leak.
Sample
public class DocIndexUpdater implements IResourceChangeListener { private TableViewer table; //assume this gets initialized somewhere private static final IPath DOC_PATH = new Path("MyProject/doc"); public void resourceChanged(IResourceChangeEvent event) { //we are only interested in POST_CHANGE events if (event.getType() != IResourceChangeEvent.POST_CHANGE) return; IResourceDelta rootDelta = event.getDelta(); //get the delta, if any, for the documentation directory IResourceDelta docDelta = rootDelta.findMember(DOC_PATH); if (docDelta == null) return; final ArrayList changed = new ArrayList(); IResourceDeltaVisitor visitor = new IResourceDeltaVisitor() { public boolean visit(IResourceDelta delta) { //only interested in changed resources (not added or removed) if (delta.getKind() != IResourceDelta.CHANGED) return true; //only interested in content changes if ((delta.getFlags() & IResourceDelta.CONTENT) == 0) return true; IResource resource = delta.getResource(); //only interested in files with the "txt" extension if (resource.getType() == IResource.FILE && "txt".equalsIgnoreCase(resource.getFileExtension())) { changed.add(resource); } return true; } }; try { docDelta.accept(visitor); } catch (CoreException e) { //open error dialog with syncExec or print to plugin log file } //nothing more to do if there were no changed text files if (changed.size() == 0) return; //post this update to the table Display display = table.getControl().getDisplay(); if (!display.isDisposed()) { display.asyncExec(new Runnable() { public void run() { //make sure the table still exists if (table.getControl().isDisposed()) return; table.update(changed.toArray(), null); } }); } } }
References:
1. http://www.eclipse.org/articles/Article-Resource-deltas/resource-deltas.html
2. http://tech.ccidnet.com/art/3741/20031215/542015_1.html
3. http://wenku.baidu.com/view/54dc16eb6294dd88d0d26b0a.html