hangke的专栏

个人经验有限,大家共享无穷

UI持久化机制

Eclipse 中 IMemento 接口定义了对象持久化方式,通过 IMemento 接口的实现类,用户能把对象持久化到文件系统中, IMemento 接口定义如例程 24-7 所示。
例程 24-7 IMemento.java
package org.eclipse.ui;
 
public interface IMemento {
    public static final String TAG_ID = "IMemento.internal.id"; //$NON-NLS-1$
 
    public IMemento createChild(String type);
 
    public IMemento createChild(String type, String id);
 
    public IMemento getChild(String type);
 
    public IMemento[] getChildren(String type);
 
    public Float getFloat(String key);
 
    public String getID();
 
    public Integer getInteger(String key);
 
    public String getString(String key);
 
    public String getTextData();
 
    public void putFloat(String key, float value);
 
    public void putInteger(String key, int value);
 
    public void putMemento(IMemento memento);
 
    public void putString(String key, String value);
 
    public void putTextData(String data);
}
Eclipse 中 XMLMemento 实现了 IMemento 接口,通过 XMLMemento 对象, Eclipse 能把当前 UI 的状态持久化到文件系统中,其中 createChild 方法为创建下一级 IMemento 节点, getChild 方法返回下一级 IMemento 节点。
24.4.2 UI 持久化与恢复的实现
Eclipse UI 的设计目标之一,就是在多次会话之间保持用户体验的连贯性。当一次会话结束时,工作台会保存当前的配置和工作台窗口的内容;用户开始新的一次会话时,工作台将这些状态恢复到上一次会话结束之前的样子。
Eclipse UI 持久化的过程比较复杂,因 UI 要持久化的内容比较多,包括编辑器、视图、视角、 page 和 window 的状态,但持久化的方式一样,持久化的步骤如下:
( 1 )创建 XMLMemento 对象,并保存,实现类为 Workbench ,如下代码片段所示。
                   XMLMemento memento = XMLMemento
                                     .createWriteRoot(IWorkbenchConstants.TAG_WORKBENCH);
                   IStatus status = saveState(memento);o);
( 2 )得到所有的工作台窗口( WorkbenchWindow ),保存所有窗口的状态,实现类为 Workbench ,如下代码片段所示。
                   IWorkbenchWindow[] windows = getWorkbenchWindows();
                   for (int nX = 0; nX < windows.length; nX++) {
                            WorkbenchWindow window = (WorkbenchWindow) windows[nX];
                            IMemento childMem = memento
                                               .createChild(IWorkbenchConstants.TAG_WINDOW);
                            result.merge(window.saveState(childMem));
                   }
( 3 )得到工作台窗口包括的 Page ( WorkbenchPage )页,并保存 Page 页的状态,实现类为 WorkbenchWindow ,如下代码片段所示。
        Iterator itr = pageList.iterator();
        while (itr.hasNext()) {
            WorkbenchPage page = (WorkbenchPage) itr.next();
 
            IMemento pageMem = memento
                    .createChild(IWorkbenchConstants.TAG_PAGE);
            pageMem.putString(IWorkbenchConstants.TAG_LABEL, page.getLabel());
            result.add(page.saveState(pageMem));
 
            if (page == getActiveWorkbenchPage()) {
                pageMem.putString(IWorkbenchConstants.TAG_FOCUS, "true"); //$NON-NLS-1$
            }
 
            IAdaptable input = page.getInput();
            if (input != null) {
                IPersistableElement persistable = (IPersistableElement) input
                        .getAdapter(IPersistableElement.class);
                if (persistable == null) {
                    WorkbenchPlugin
                            .log("Unable to save page input: " //$NON-NLS-1$
                                    + input
                                    + ", because it does not adapt to IPersistableElement");
                } else {
                    IMemento inputMem = pageMem
                            .createChild(IWorkbenchConstants.TAG_INPUT);
                    inputMem.putString(IWorkbenchConstants.TAG_FACTORY_ID,
                            persistable.getFactoryId());
                    persistable.saveState(inputMem);
                }
            }
        }
( 4 )保存 Page 页中所有的编辑器、视图、视角的状态,通过 EditorManager 、 ViewFactory 和 Perspective 保存编辑器、视图、视角的状态,实现类为 WorkbenchPage ,如下代码片段所示。
        IMemento childMem = memento
                .createChild(IWorkbenchConstants.TAG_EDITORS);
        result.merge(editorMgr.saveState(childMem));
 
        childMem = memento.createChild(IWorkbenchConstants.TAG_VIEWS);
        result.merge(getViewFactory().saveState(childMem));
        Iterator itr = perspList.iterator();
        while (itr.hasNext()) {
            Perspective persp = (Perspective) itr.next();
            IMemento gChildMem = childMem
                    .createChild(IWorkbenchConstants.TAG_PERSPECTIVE);
            result.merge(persp.saveState(gChildMem));
        }
( 5 )把最底层的 XMLMemento 保存到文件,实现类为 Workbench ,如下代码片段所示。
         private boolean saveMementoToFile(XMLMemento memento) {
                   File stateFile = getWorkbenchStateFile();
                   if (stateFile == null)
                            return false;
                   try {
                            FileOutputStream stream = new FileOutputStream(stateFile);
                            OutputStreamWriter writer = new OutputStreamWriter(stream, "utf-8");
                            memento.save(writer);
                            writer.close();
                   } catch (IOException e) {
                            stateFile.delete();
                            MessageDialog.openError((Shell) null,
                                               WorkbenchMessages.SavingProblem,
                                              WorkbenchMessages.ProblemSavingState);
                            return false;
                   }
 
                   return true;
         }
如上的步骤只是列出了持久化的过程,并没有完全列出持久化的所有代码,读者可以通过实现类找到具体代码的实现。
当 Eclipse 重新启动时, Eclipse 将通过从文件中读取相应的 XMLMemento 信息 ,恢复上一次退出 Eclipse 时的状态,具体步骤如下:
( 1 )从文件中读取 XMLMemento 信息,实现类为 Workbench ,如下代码片段如示。
                   final File stateFile = getWorkbenchStateFile();
                   if (stateFile == null || !stateFile.exists()) {
                            String msg = WorkbenchMessages.Workbench_noStateToRestore;
                            return new Status(IStatus.WARNING, WorkbenchPlugin.PI_WORKBENCH,
                                               IWorkbenchConfigurer.RESTORE_CODE_RESET, msg, null);
                   }
                   FileInputStream input = new FileInputStream(stateFile);
                   BufferedReader reader = new BufferedReader(
                                                        new InputStreamReader(input, "utf-8"));
                   IMemento memento = XMLMemento.createReadRoot(reader);
         ….
        IStatus restoreResult = restoreState(memento);
( 2 )从 XMLMemento 读取所有窗口信息,并恢复窗口,实现类为 Workbench ,如下代码片段所示。
                   IMemento[] children = memento
                       .getChildren(IWorkbenchConstants.TAG_WINDOW);
                  
                   createdWindows = new WorkbenchWindow[children.length];
                  
                   for (int i = 0; i < children.length; i++) {
                            childMem = children[i];
                            WorkbenchWindow newWindow = newWorkbenchWindow();
                            createdWindows[i] = newWindow;
                            newWindow.create();
                           
                            windowManager.add(newWindow);
                           
                            boolean restored = false;
                            try {
                                     status.merge(newWindow.restoreState(childMem, null));
                                     try {
                                               newWindow.fireWindowRestored();
                                     } catch (WorkbenchException e) {
                                               status.add(e.getStatus());
                                     }
                                     restored = true;
                            } finally {
                                     if (!restored) {
                                               createdWindows[i] = null;
                                               newWindow.close();
                                     }
                            }
                   }
( 3 )恢复所有 Page 的状态,实现类为 WorkbenchWindow ,如下代码片段所示。
            WorkbenchPage newPage = null;
            try {
                newPage = new WorkbenchPage(this, input);
                result.add(newPage.restoreState(pageMem, activeDescriptor));
                pageList.add(newPage);
                firePageOpened(newPage);
            } catch (WorkbenchException e) {
                WorkbenchPlugin
                        .log("Unable to restore perspective - constructor failed.", e);
                result.add(e.getStatus());
                continue;
            }
( 4 )恢复所有编辑器、视图和视角的状态,通过 EditorManager 、 ViewFactory 和 Perspective 恢复编辑器、视图、视角的状态,实现类为 WorkbenchPage ,如下代码片段所示。
                IMemento childMem = memento
                        .getChild(IWorkbenchConstants.TAG_EDITORS);
                result.merge(getEditorManager().restoreState(childMem));
   
                childMem = memento.getChild(IWorkbenchConstants.TAG_VIEWS);
                if (childMem != null)
                    result.merge(getViewFactory().restoreState(childMem));
                IMemento perspMems[] = childMem
                        .getChildren(IWorkbenchConstants.TAG_PERSPECTIVE);
                Perspective activePerspective = null;
                for (int i = 0; i < perspMems.length; i++) {
                    try {
                        Perspective persp = new Perspective(null, this);
                        result.merge(persp.restoreState(perspMems[i]));
                        IPerspectiveDescriptor desc = persp.getDesc();
                        if (desc.equals(activeDescriptor))
                            activePerspective = persp;
                        else if ((activePerspective == null)
                                && desc.getId().equals(activePerspectiveID))
                            activePerspective = persp;
                        perspList.add(persp);
                        window.firePerspectiveOpened(this, desc);
                    } catch (WorkbenchException e) {
                    }
                }
Eclipse 中, EditorManager ViewFactory 负责编辑器和视图的持久化和恢复,另外还处理编辑器和视图的相关操作,读者可以跟踪 EditorManager ViewFactory 中的方法,了解跟编辑器和视图持久化的实现。  
阅读更多
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭