Persisting State of Components

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)里。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
15:58:08: 为项目CTK执行步骤 ... 15:58:08: Persisting CMake state... 15:58:19: 正在启动 "D:\BaiduNetdiskDownload\cmake-3.16.0-win64-x64\bin\cmake.exe" --build . --target all Scanning dependencies of target Log4Qt [ 4%] Creating directories for 'Log4Qt' [ 8%] Performing download step (git clone) for 'Log4Qt' Cloning into 'Log4Qt'... fatal: unable to access 'https://github.com/MEONMedical/Log4Qt.git/': OpenSSL SSL_read: Connection was reset, errno 10054 Cloning into 'Log4Qt'... fatal: unable to access 'https://github.com/MEONMedical/Log4Qt.git/': OpenSSL SSL_read: Connection was reset, errno 10054 Cloning into 'Log4Qt'... fatal: unable to access 'https://github.com/MEONMedical/Log4Qt.git/': Failed to connect to github.com port 443: Timed out -- Had to git clone more than once: 3 times. CMake Error at Log4Qt-cmake/tmp/Log4Qt-gitclone.cmake:31 (message): Failed to clone repository: 'https://github.com/MEONMedical/Log4Qt.git' NMAKE : fatal error U1077: “D:\BaiduNetdiskDownload\cmake-3.16.0-win64-x64\bin\cmake.exe”: 返回代码“0x1” Stop. NMAKE : fatal error U1077: “"C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\BIN\amd64\nmake.exe"”: 返回代码“0x2” Stop. NMAKE : fatal error U1077: “"C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\BIN\amd64\nmake.exe"”: 返回代码“0x2” Stop. 15:59:23: 进程"D:\BaiduNetdiskDownload\cmake-3.16.0-win64-x64\bin\cmake.exe"退出,退出代码 2 。 Error while building/deploying project CTK (kit: cmake-3.16.0) The kit cmake-3.16.0 has configuration issues which might be the root cause for this problem. When executing step "CMake Build"
07-22

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值