追蹤資源變更

資源外掛程式併入事件機制來通知資源特別有關係的變更。如果您需要在執行外掛程 式的同時追蹤資源樹狀結構變更,您可以向工作區登錄 IResourceChangeListener 。 您的接聽器會透過說明變更的 IResourceChangeEvent 物件收到變更通知。

資源變更處理程序

若要追蹤資源變更,您必須向工作區登錄資源變更接聽器。

IResourceChangeListener listener = new MyResourceChangeReporter();
ResourcesPlugin.getWorkspace().addResourceChangeListener(
    listener, IResourceChangeEvent.POST_CHANGE);

如果工作區資源做過修正,您的接聽器便會收到通知。修改資源的資源 API 方法將 這些事件觸發為它們記錄操作方式的一部份。資源 API 的方法註解明確地陳述它是 否觸發了資源變更事件。例如,下列併入 IFile.createContents() 註解中:

此方法變更資源;這些變更將在後續的資源變更事件中報告,包括對此檔案內容 已變更的指示。

建立、除去或變更資源的方法通常會觸發這些事件。讀取但不寫入資源的方法通常不 會觸發這些事件。

批次變更和資源差量

如果您需要一次修改一些資源,您可以透過批次方式處理資源變更 API 呼叫,使得 整個變更僅傳送一個資源變更事件。 IWorkspace.run(runnable, monitor) 用來批次處理作業。當完成指定的 runnable,資源變更事件才傳送給登錄的 接聽器。在 runnable 中建立的任何附加的(巢狀)Runnable 將被視為母項批次作 業的一部份,而在那些 runnable 中所做的資源變更會出現在母項的資源變更通知中。

當可以限制廣播許多小變更的額外負荷時,您應該批次處理您的變更。批次 處理如果失敗,可能會使系統湧進大量資源變更通知及自動建置。

資源變更事件說明工作區中發生的變更特性(或變更集)。此事件包含一個 資源 差量,它說明變更的網路效能。例如,如果您新增某個資源而稍後在一 個批次變更期間除去了它,該資源不會在差量中出現。

資源差量建構為在工作區根目錄啟動的樹狀結構。資源差量樹狀結構說明這些變更類 型:

欲遍訪資源差量樹狀結構,您可以實作 IResourceDeltaVisitor 介面或使用 IResource.getAffectedChildren 來明確地遍訪樹狀結構。資源 差量訪客實作資源差量呼叫的 visit 方法,因為它列舉樹狀結構中每一個變 更。

附註:對資源階段作業內容或資源持續性內容所做的變更不會在資源差量中識 別。

資源變更事件

每當工作區有變更(或批次處理的變更集)時,便會傳送資源變更事件。 此外,也會針對某些特定的工作區作業傳送資源變更事件。下表彙總資源變更事件的 類型及報告的時間。

事件類型

說明

PRE_CLOSE

通知接聽器專案即將關閉。此事件可用來擷取及儲存專案關閉前記憶體中表示法(例 如,階段作業內容)的必要資訊。(當專案關閉時,便會除去記憶體中表示法)。 在這個事件期間,工作區會被鎖定(無法更新任何資源)。在工作區關閉期間也會觸 發 PRE_CLOSE 事件,因為所有開啟的專案都會被關閉。此事件包含已關閉的 專案。

PRE_DELETE

通知接聽器專案即將除去。此事件可用來執行清除作業,例如從您外掛程式目錄中除去與專案相關的任何已儲存狀態。在這個事件期間,工作區會被鎖定(無法更 新任何資源)。此事件包含已除去的專案。

PRE_AUTOBUILD

發生任何自動建置前通知接聽器。當平台偵測到必須發生的自動建置,無論自 動建置是否真的啟用了,都會傳佈這個事件。在這個事件期間,工作區不 會被鎖定(可更新資源)。 此事件包含一個資源差量,它說明上次報告 POST_CHANGE 事件後所發生的變 更。

POST_AUTOBUILD

在發生任何自動建置後通知接聽器。在平台執行自動建置後,無論自動建置是否真的 啟用了,都會廣播這個事件。在這個事件期間,工作區不會被鎖定( 可更新資源)。 此事件包含一個資源差量,它說明上次報告 POST_CHANGE 事件後所發生的變 更。

POST_CHANGE

說明上次報告 POST_CHANGE 事件後工作區發生的一組變更。在個別使用資 源變更 API 或在一組批次處理的工作區變更後觸發。也會在完成任何 PRE_AUTOBUILDPOST_AUTOBUILD 通知後觸發。 此事件包含一個資源差量,它說明上次 POST_CHANGE 事件後的網路變更。 在這個事件期間,工作區會被鎖定(無法更新任何資源)。

實作資源變更接聽器

下列範例實作主控台型資源變更接聽器。針對特定事件類型和輸出至主控台的這些事 件相關資訊登錄資源變更接聽器。

IResourceChangeListener listener = new MyResourceChangeReporter();
ResourcesPlugin.getWorkspace().addResourceChangeListener(listener,
    IResourceChangeEvent.PRE_CLOSE
    | IResourceChangeEvent.PRE_DELETE
    | IResourceChangeEvent.PRE_AUTO_BUILD
    | IResourceChangeEvent.POST_AUTO_BUILD
    | IResourceChangeEvent.POST_CHANGE);

接聽器檢查每一個事件類型並報告變更的資源和發生的變更種類之相關資訊。 雖然這個範例是設計來顯示一個處理所有源事件類型的一般接聽器,但典型接聽器僅登 錄一種事件類型。

POST_CHANGE 的實作使用可用來造訪資源差量中變更的另一個類別。

import org.eclipse.resources.*;
import org.eclipse.runtime.*;
public class MyResourceChangeReporter implements IResourceChangeListener {
    public void resourceChanged(IResourceChangeEvent event) {
        IResource res = event.getResource();
        switch (event.getType()) {
            case IResourceChangeEvent.PRE_CLOSE:
                System.out.print("Project ");
                System.out.print(res.getFullPath());
                System.out.println(" is about to close.");
                break;
            case IResourceChangeEvent.PRE_DELETE:
                System.out.print("Project ");
                System.out.print(res.getFullPath());
                System.out.println(" is about to be deleted.");
                break;
            case IResourceChangeEvent.POST_CHANGE:
                System.out.println("Resources have changed.");
                event.getDelta().accept(new DeltaPrinter());
                break;
            case IResourceChangeEvent.PRE_AUTO_BUILD:
                System.out.println("Auto build about to run.");
                event.getDelta().accept(new DeltaPrinter());
                break;
            case IResourceChangeEvent.POST_AUTO_BUILD:
                System.out.println("Auto build complete.");
                event.getDelta().accept(new DeltaPrinter());
                break;

        }
    }
}

DeltaPrinter 類別實作 IResourceDeltaVisitor 介面來詢問資源差量。針對資源差量中每一個資源變更呼叫 visit() 方法。 訪客使用回覆值來指示是否應造訪子項資源的差量。

class DeltaPrinter implements IResourceDeltaVisitor {
    public boolean visit(IResourceDelta delta) {
        IResource res = delta.getResource();
        switch (delta.getKind()) {
            case IResourceDelta.ADDED:
                System.out.print("Resource ");
                System.out.print(res.getFullPath());
                System.out.println(" was added.");
                break;
            case IResourceDelta.REMOVED"
                System.out.print("Resource ");
                System.out.print(res.getFullPath());
                System.out.println(" was removed.");
                break;
            case IResourceDelta.CHANGED:
                System.out.print("Resource ");
                System.out.print(res.getFullPath());
                System.out.println(" has changed.");
                break;
        }
        return true; // 造訪子項
    }
}

進一步資訊可從提供的資源差量取得。下列片段顯示如何實作 IResourceDelta.CHANGED 案例來進一步說明資源變更。

...
case IResourceDelta.CHANGED:
    System.out.print("Resource ");
    System.out.print(delta.getFullPath());
    System.out.println(" has changed.");
    switch (delta.getFlags()) {
        case IResourceDelta.CONTENT:
            System.out.println("--> Content Change");
            break;
        case IResourceDelta.REPLACED:
            System.out.println("--> Content Replaced");
            break;
        case IResourceDelta.REMOVED:
            System.out.println("--> Removed");
            break;
        case IResourceDelta.MARKERS:
            System.out.println("--> Marker Change");
            IMarkerDelta[] markers = delta.getMarkerDeltas();
            // 如果 對標示元有興趣,請檢查這些差量
            break;
    }
    break;
...

如需資源差量、訪客和標示元差量的完整說明,請參考 API 規格的 IResourceDeltaIResourceDeltaVisitorIMarkerDelta

附註: 當您啟動外掛程式,資源變更接聽器對追蹤資源發生的變更非常有用。 如果您的外掛程式在啟動碼期間登錄資源變更接聽器,則在啟動外掛程式前可能會觸 發許多資源變更事件。您外掛程式接收的第一個資源變更事件內含的資源差量將不含 外掛程式上次啟動後所做的全部變更。如果您需要追蹤外掛程式活動間所做的變更, 您應該使用針對工作區儲存所提供的支援。此說明於 工作區儲存參與中。