码迷,mamicode.com
首页 > 其他好文 > 详细

Persisting State of Components

时间:2014-11-24 17:13:31      阅读:234      评论:0      收藏:0      [点我收藏+]

标签:intellij idea   插件   持久化   state   状态   

IntelliJ IDEA组件的持久化状态

IntelliJ IDEA提供了允许组件或服务在IntelliJ IDEA每次重启之间保持它们的状态的API。你可以使用一个简单的API保存少量值,也可以使用PersistentStateComponent接口为更复杂的组件的状态进行持久化。

使用PropertiesComponent进行简单的持久化

如果你的插件需要持久化的只是少量简单的值,最容易实现的方式是使用com.intellij.ide.util.PropertiesComponent服务。它即可以在保存application级的值,也可以保存project水平的值(保存在workspace文件中)。

使用PropertiesComponent.getInstance()方法来保存application水平的值,使用PropertiesComponent.getInstance(Project)方法来保存project水平的值。
因为所有的插件共用同一命名空间,因此高度推荐为你的Key名称增加前缀(比如你的插件ID)。

使用PersistentStateComponent

com.intellij.openapi.components.PersistentStateComponent为你提供了定义要持久化的值、它们的格式、存储位置等大多数的灵活性。要使用它,你需要标记组件或服务实现PersistentStateComponent接口、定义状态类并使用@com.intellij.openapi.components.State标注指定存储位置。

注意(仅)通过实现PersistentStateComponent,扩展的实例不能保存它们的状态。如果你的扩展需要有持久化状态,你需要定义一个单独的服务来负责管理那个状态。(附原文:Note that instances of extensions cannot persist their state by implementing PersistentStateComponent. If your extension needs to have persistent state, you need to define a separate service responsible for managing that state.我实际写的代码里并没有实现一个单独的服务,只是把PersistentStateComponent实现类注册成了application component,持久化也工作了……原文是要表达什么意思不太明白,欢迎回复讨论。)

实现PersistentStateComponent接口

PersistentStateComponent实现类需要通过状态类类型参数化。状态类可以是独立的JavaBean类,也可以是实现PersistentStateComponent的类本身。

前一种情况,通常状态类的实例作为PersistentStateComponent实现类的一个field(在内存中)存储:

class MyService implements PersistentStateComponent<MyService.State> {
    class State {
        public String value;
    }

    State myState;

    public State getState() {
        return myState;
    }

    public void loadState(State state) {
        myState = state;
    }
}

后一种情况下,你可以使用如下模式实现getState()和loadState()方法:

class MyService implements PersistentStateComponent<MyService> {
    public String stateValue;

    public MyService getState() {
        return this;
    }

    public void loadState(MyService state) {
        XmlSerializerUtil.copyBean(state, this);
    }
}

实现State类

PersistentStateComponent实现类通过将public field和bean的属性序列化为XML格式来工作。如下类型的值可以被持久化:

  • 数字(包括基础类型如int和封装类型如Integer);
  • 布尔值;
  • 字符串;
  • 集合;
  • 映射;
  • 枚举。

要排除一个public field或bean属性的序列化,你可以使用@com.intellij.util.xmlb.annotations.Transient标注对field或getter进行注释。

注意状态类必须有一个默认构造器。它应返回组件的默认状态(将用于还没有任何XML持久数据的情况)。

定义存储位置

为了准确的指定持久值要存储的位置,你需要为PersistentStateComponent实现类增加一个@State注释。它需要如下字段:

  • name(必需) - 指定状态的名称(XML中的根标记名称)
  • 一个或更多@com.intellij.openapi.components.Storage注释(必需) - 为.ipr和基于文件夹的project指定存储位置。
  • roamingType(com.intellij.openapi.components.RoamingType,可选) - 指定当IDEA Server插件启用时,在不同IDEA安装之前是否启用状态同步。(不了解IDEA Server plugin,附原文:specifies whether the state is synchronized between different IDEA installations when the IDEA Server plugin is used)
  • reloadable(可选) - 如果设为否,当XML文件被外部修改或状态变更时,需要project完全重新加载。

最简单地指定@Storage注释的方式如下:

  • @Storage(id=”other”, file = StoragePathMacros.APP_CONFIG + “/other.xml”) 用于application水平的值
  • @Storage(id=”other”, file = StoragePathMacros.PROJECT_FILE) 用于值保存在project文件(对于基于.ipr文件的project)中的情况
  • @Storage(id = “dir”, file = StoragePathMacros.PROJECT_CONFIG_DIR + “/other.xml”, scheme = StorageScheme.DIRECTORY_BASED)}) 用于值保存在project文件夹(对于基于文件夹的project)中的情况
  • @Storage(id=”other”, file = StoragePathMacros.WORKSPACE_FILE) 用于值保存在workspace文件中的情况

@Storage注释的id参数可以用来按指定的格式排除指定field的序列化(译者未试验)。如果你不需要排除任何内容,你可以指定id为任意字符串值。

通过为file参数指定不同的值,你可以使状态持久化不同的文件中。

当使用基于文件夹的项目格式时,如果你需要指定值保存的位置,你需要增加第二个@Storage注释,其包含一个值被设为StorageScheme.DIRECTORY_BASED的scheme参数,例如:

@State(
    name = "AntConfiguration",
    storages = {
        @Storage(id = "default", file = StoragePathMacros.PROJECT_FILE),
        @Storage(id = "dir", file = StoragePathMacros.PROJECT_CONFIG_DIR + "/ant.xml", scheme = StorageScheme.DIRECTORY_BASED)
    }
)

自定义持久化值的XML格式

如果你要持久化状态并不简洁的匹配一个JavaBean,你可以使用org.jdom.Element作为状态类。在这种情况下,你可以使用getState()方法来构建一个具有任意结构的会被直接保存到状态XML文件中的XML元素。在loadState()方法中,你可以使用自定义的逻辑对JDOM元素树进行反向序列化。

如果你想使用默认的bean序列化但又需要自定义XML存储格式(例如,适应你的插件的旧版本或外部定义的XML格式),你可以使用@Tag、@Attribute、@Property、@MapAnnotation、@AbstractCollection注释。你可以查阅源代码(com.intellij.util.xmlb包下)来获取更多这些注释的意义的信息。

持久化组件的生命周期

当组件被创建后或保持持久化状态的XML文件被外部修改(如project文件被版本控制系统更新)时,loadState()方法被调用(仅当组件存在无默认值的持久化状态时)。在后一种情形下,组件要负责更新UI和其他依据此被修改状态的相关组件。

getState()方法在每次设置保存时(如当窗口失去焦点或IDE关闭时)调用。 如果getState()方法返回的状态与默认状态(由使用默认构造器创建的状态类获取)相等,那么什么都不会持久化到XML里。否则,返回的状态会被序列化为XML并存储。

经典API(JDOMExternalizable)

旧版的IDEA组件使用JDOMExternalizable接口持久化状态。它使用readExternal()方法从JDOM元素中读取状态,使用writeExternal()方法向其写入状态。JDOMExternalizable实现类可以手动地在属性和子元素中存储状态,使用DefaultJDOMExternalizer类来自动地存储所有的public field值。

当组件的类实现JDOMExternalizable接口时,组件将其状态保存到以下文件:

  • Project组件保存其状态到project文件(.ipr)。然而,如果plugin.xml文件中workspace选项值为true,组件会将其配置保存到workspace文件(.iws)。
  • Module组件保存其状态到module文件(.iml)里。

Persisting State of Components

标签:intellij idea   插件   持久化   state   状态   

原文地址:http://blog.csdn.net/hawkdowen/article/details/41447571

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!