Eclipse 資源改變通知機制

來源:互聯網
上載者:User
Resource Change Listener

介面: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);

在資源改變的通知期間,workspace 會
locked 來避免產生更多的通知。

 

Resource API

Resource API 在執行
creating,copying,moving 和 deleting
操作時會向外廣播資源改變事件。

資源操作會嵌套,如 Ifile.move 操作會觸發一個
Ifile.create 操作建立新的檔案,然後再觸發一個 Ifile.delete
操作刪除老檔案。所以一個 Ifile.move 操作嵌套了一個
Ifile.create 操作和一個
Ifile.delete 操作,但是以上操作只會通知一次

 

Batching Changes

    當有一批資源改變事件需要通知時,需要採用Batching的方式來提高效能。這樣能保證只有一個資源改變事件被廣播了出去,而不是多個。

   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不再保證IworkspaceRunnable它在執行期間會阻止其他的通知發生。這樣做的原因是為了保證能夠在通知發生期間能夠使UI相應使用者事件。

eclipse 3.0中引入了一個新類WorkspaceJob,可以將大量的Workspace資源改變操作放到一個Job中在後台執行。

一個更強大的特點當資源在Workspace外部被更改ResourceChangeListener也會被通知到,比如直接對檔案系統的檔案變更。由於大多數的作業系統並沒有這種機制,所以需要執行Iresource.refreshLocal操作後,資源改變會通知所有的Listener。

 

IResourceChangeEvent

l         Event Type

PRE_CHANGE,POST_CHANGE,PRE_BUILD,POST_BUILD,PRE_CLOSE,POST_CLOSE,PRE_DELETE,POST_DELETE

l         IresourceDelta

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的效能

    Resource Change Listener的實現應該是輕量級的,並且能夠快速執行。資源改變的通知會被經常的發出,如果Listener的效能不高,將會影響整個平台的效能。如果在Listener中有大量的工作需要做,最好將它放到後台線程中執行。

    使用IResourceDelta.findMember(IPath)可以快速定位到我們關注的IresourceDelta,而不必按樹狀結構依次向下通知。

    IresourceDelta.accept(IResourceDeltaVistor)來訪問我們關心的ResourceDeltaVistor樹的分支。

    安全執行緒問題:我們不能控制我們的Listener會在哪一個線程中執行。Workspace操作會出現在任何的線程中,Resource
Change Listener也會運行在觸發該操作的任何線程中。如果我們想讓我們的更新操作出現在一個特定的線程中,我們不得不確保代碼被post到那個線程。通常我們要更新使用者介面,就先得到UI的Display對象,使用Display.syncExec()或者Display.asyncExec()方法。

    如果採用非同步方式執行,需要注意ResourceDelta都有一個“expire date”.如果傳遞一個IresourceDelta到另外一個線程,如果Listener的ResourceChanged()方法已經在另外一個線程中返回,對IresourceDelta的引用將會發生錯誤。請確保Listener不會一直儲存Resource
Delta的引用,因為這些Resource Delta的數量是很大的,如果一直保持對其引用,會導致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);               }            });         }      }   }

 

參考文獻:

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

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.