20230203IDEA插件开发-Action的实现

背景

开发的插件点击后UI卡住,怀疑是阻塞了UI线程。。。。仔细看下文档

文档翻译-Action的实现

自定义的action类是派生自抽象类 AnAction的子类。当用户操作菜单项或工具栏按钮时,IDEA会调用action的方法

基于 AnAction 的类不能包含任何属性,因为 AnAction 的实例会存在 application整个生命周期。如果 AnAction 类使用了属性存储了短声明周期的数据但没有合理的清除,会造成内存泄漏。例如如果你把Project对象存到了这里,当用户关闭了这个Project之后就会发生内存泄漏

方法Override覆盖原则

每个action可以覆盖 AnAction.update(),必须覆盖AnAction.actionPerformed().

AnAction.update() 用来被IDEA调用更新action的状态,action是否可用/是否可见取决于action在当前UI上是否可用.AnActionEvent 对象会传递给这个方法并且包含当前action上下文的信息。可以通过修改和事件上下文关联的Presentation对象状态来改变action是否可用。像Overriding the AnAction.update() Method说的一样, update() 方法的执行速度非常重要

2022.3+版本后AnAction.getActionUpdateThread() 返回 ActionUpdateThread 线程决定了 update() 方法是否在 background thread (BGT) or the event-dispatching thread (EDT)上被调用。首选的方式是在BGT上执行update方法, 这样可以保证application侧读取 PSIthe virtual file system (VFS), 或 project models的有利条件。在BGT上运行update的Actions不应该直接访问Swing 组件的结构。 反之EDT上运行的update的Action必须禁止访问PSI, VFS, 或 project的数据,但可以访问Swing组件和其他UI模型。所有由DataContext 提供的可访问数据在这里有说明 Determining the Action Context. 当必须从BGT切换回EDT时,需要使用 AnActionEvent.getUpdateSession()方法获得 UpdateSession 并调用 UpdateSession.compute() 在EDT上运行方法。从2022.3开始,插件的DevKit将会有检查 Plugin DevKit | Code | ActionUpdateThread 是否丢失,来提醒插件作者实现这个方法

AnAction.actionPerformed() 将会在可用之后当用户选择action时被IDEA调用。这个方法是实现action最麻烦的任务,它包含了当action被调用时要执行的代码。 actionPerformed()方法也接收一个 AnActionEvent作为参数,它用来访问任何上下文相关的信息例如 projects, files, selection。。。参考Overriding the AnAction.actionPerformed() Method 获取更多信息

这里还有其他的方法可以在 AnAction 类中被覆盖,例如改变action默认的 Presentation。还有一个使用场景可以通过覆盖构造器来达成,当动态注册到分组的时候demo可以在这里看到Grouping Actions

AnAction.update 

IDEA会周期性的调用AnAction.update() 方法来响应用户的操作。 update() 方法用于动态判断action在当前上下文是否应该禁用或启用。方法的实现必须确保可用性状态和可见性状态 ,否则指定的action将会”卡住”。(译者注:这里的意思应该是从用户看来是卡住的现象,实际就是没响应任何动作)

AnAction.update()方法可能在UI线程上频繁的调用。所以这个方法必须非常快的执行,没有必须执行的实际动作。例如检查选中的对象是否可用,但不做任何文件系统相关的动作。如果新的状态无法被快速的确定是否可用,判定过程应该在AnAction.actionPerformed()中执行,并通知notify用户这个动作在当前上下文不能被执行

线程

//TODO

参考

https://plugins.jetbrains.com/docs/intellij/basic-action-system.html

https://plugins.jetbrains.com/docs/intellij/general-threading-rules.html#modality-and-invokelater

0 Comments
Leave a Reply