工作區儲存處理程序會在使用者關閉工作台時觸發,以及由平台在其他時間定期觸發 。外掛程式可參與工作區儲存處理程序,以便在儲存剩餘的工作區持續性資 料時將重要的外掛程式資料存入磁碟。
工作區儲存程序亦可用來追蹤您外掛程式活動期間發生的變更。
如果要參與工作區儲存,您必須將儲存參與者新增至工作區。 這通常在您外掛程式啟動方法期間完成。這也是讀取外掛程式上次關閉時所儲存任何狀態的地方。
讓我們看一個示範儲存程序的簡式外掛程式。
package com.example.saveparticipant; import org.eclipse.core.runtime.*;import org.eclipse.core.resources.*;import java.io.File;import java.util.*; public class MyPlugin extends Plugin { private static MyPlugin plugin; public MyPlugin(IPluginDescriptor descriptor) { super(descriptor); plugin = this; } public static MyPlugin getDefault() { return plugin; } protected void readStateFrom(File target) { } public void startup() throws CoreException { super.startup(); ISaveParticipant saveParticipant = new MyWorkspaceSaveParticipant(); ISavedState lastState = ResourcesPlugin.getWorkspace().addSaveParticipant(this, saveParticipant); if (lastState == null) return; IPath location = lastState.lookup(new Path("save")); if (location == null) return; // 外掛程式實例應該從檔案讀取任何重要狀態。 File f = getStateLocation().append(location).toFile(); readStateFrom(f); } protected void writeImportantState(File target) { } }
ISaveParticipant 定義工作區儲存參與者使用的通訊協定。 這個介面的實作者可提供不同儲存程序階段的行為。讓我們查看各階段及類 別 WorkspaceSaveParticipant 實作每一個步驟的方式。
public void prepareToSave(ISaveContext context) throws CoreException { }
public void saving(ISaveContext context) throws CoreException { switch (context.getKind()) { case ISaveContext.FULL_SAVE: MyPlugin myPluginInstance = MyPlugin.getDefault(); // 儲存外掛程式狀態 int saveNumber = context.getSaveNumber(); String saveFileName = "save-" + Integer.toString(saveNumber); File f = myPluginInstance.getStateLocation().append(saveFileName).toFile(); // 如果我們無法寫入,則有一個異常狀況會擲出,且我們不會更新路徑 myPluginInstance.writeImportantState(f); context.map(new Path("save"), new Path(saveFileName)); context.needSaveNumber(); break; case ISaveContext.PROJECT_SAVE: // 取得與這個儲存作業相關的專案 IProject project = context.getProject(); // 必要的話,儲存這項資訊 break; case ISaveContext.SNAPSHOT: // 這項作業必須快速執行,因為 // 工作區經常會要求 // Snapshot。 break; } }
ISaveContext 說明儲存作業的相關資訊。儲存作業有三種:FULL_SAVE、 SNAPSHOT 及 PROJECT_SAVE。儲存參與者應謹慎執行適合所 收到儲存事件種類的處理程序。例如,瞬間快照事件可能經常發生且指定讓 外掛程式儲存它們的重要狀態。花太多時間來儲存當機事件中可重新計算的 狀態會使平台速度降低。
儲存號碼用來建立使用序列號碼(save-1、save-2...等等)命 名的資料儲存檔。每一個儲存檔對映到一個屬於獨立儲存號碼的邏輯檔名(save)。外掛程式資料寫入對應檔且稍後可擷取,無需知道上次成功儲存作 業的特定儲存號碼。取回在我們的外掛程式啟動碼中看過的這個技術:
IPath location = lastState.lookup(new Path("save"));儲存我們的資料及對映檔名後,呼叫 needSaveNumber 來指示我們已參與工 作區儲存且要指定號碼給儲存活動。 儲存號碼可用來建立如上所示的資料檔。
public void doneSaving(ISaveContext context) { MyPlugin myPluginInstance = MyPlugin.getDefault(); // 刪除舊的儲存狀態,因為不再需要它 int previousSaveNumber = context.getPreviousSaveNumber(); String oldFileName = "save-" + Integer.toString(previousSaveNumber); File f = myPluginInstance.getStateLocation().append(oldFileName).toFile(); f.delete(); }
在此,我們清除上一個儲存作業中的儲存資訊。我們使用 getPreviousSaveNumber 來取得在上一個儲存作業(不是剛才完成的儲存作 業)中指定的儲存號碼。我們使用這個號碼來建構需要除去的檔名。請 注意:我們不使用儲存狀態的邏輯檔對映,因為我們已對映現行儲存檔號碼。
public void rollback(ISaveContext context) { MyPlugin myPluginInstance = MyPlugin.getDefault(); // 因為儲存作業失敗,請刪除剛才寫入的儲存狀態 int saveNumber = context.getSaveNumber(); String saveFileName = "save-" + Integer.toString(saveNumber); File f = myPluginInstance.getStateLocation().append(saveFileName).toFile(); f.delete(); }
在此,我們除去剛才儲存的狀態。請注意:我們使用現行儲存號碼來建 構剛才儲存檔案之檔名。我們不需要擔心對映這個檔名到 ISaveContext 的事實。當儲存作業失敗時,平台會捨棄這個環境定義。
如果您的外掛程式在儲存生命週期的任何時候擲出異常狀況,則會從現行儲存作 業中除去且不會取得任何剩餘的生命週期方法。比方說,如果您在 saving 方法期間失敗,您不會收到 rollback 或 doneSaving 訊息。
當您將儲存參與者新增至工作區時,會傳回 ISavedState 物件,其說明外掛程式上次儲存作業期間的儲存狀態(或如果您的外掛程式先前沒有 儲存任何狀態,則為 null)。這個物件可用來存取上一個儲存檔中的資訊( 使用儲存號碼和檔案對映),或用來處理外掛程式活動期間發生的變更。
如果檔案對映是用來儲存根據儲存號碼以邏輯方式命名的檔案,則此相同對映可用來擷 取上次已知儲存狀態中的資料。
ISaveParticipant saveParticipant = new MyWorkspaceSaveParticipant(); ISavedState lastState = ResourcesPlugin.getWorkspace().addSaveParticipant(myPluginInstance, saveParticipant); if (lastState != null) { String saveFileName = lastState.lookup(new Path("save")).toString(); File f = myPluginInstance.getStateLocation().append(saveFileName).toFile(); // 外掛程式實例應該從檔案讀取任何重要狀態。 myPluginInstance.readStateFrom(f); }
取回您外掛程式啟動前可能在工作區中發生的任何資源變更事件數量。 如果您要知道外掛程式取消啟動後發生了什麼變更,即使您不需要儲存其他任何資料 ,也可以使用儲存機制來這麼做。
儲存參與者必須要求平台保存它那方面的資源差異。這屬於儲存作業的一部分。
public void saving(ISaveContext context) throws CoreException { // 外掛程式不儲存任何狀態,但要求 // 在下次啟動時使用資源差異。 context.needDelta(); }
在外掛程式啟動期間,可存取上一個儲存狀態,以及針對上次儲存後發生的所有變更 建立變更事件。
ISaveParticipant saveParticipant = new MyWorkspaceSaveParticipant(); ISavedState lastState = ResourcesPlugin.getWorkspace().addSaveParticipant(myPluginInstance, saveParticipant); if (lastState != null) { lastState.processResourceChangeEvents(new MyResourceChangeReporter()); }
提供的類別必須實作 IResourceChangeListener ,如追蹤資源變更中所述。上次儲存後的變更報告為 POST_AUTO_BUILD 資源變更事件的一部分。
附註: 儲存於 ISavedState 的變更事件中不會報告標記變更。 您必須假設任何或所有標記在您儲存上次狀態之後都已變更。