Action:菜单、工具栏与快捷入口¶
Action 是 IntelliJ Platform 中响应用户操作的基本入口。菜单项、工具栏按钮、上下文菜单、快捷键和 Find Action 中的命令通常都由 Action 实现。
最小 Action¶
package com.example.myplugin
import com.intellij.openapi.actionSystem.AnAction
import com.intellij.openapi.actionSystem.AnActionEvent
import com.intellij.openapi.actionSystem.ActionUpdateThread
import com.intellij.openapi.ui.Messages
class ShowProjectInfoAction : AnAction() {
override fun getActionUpdateThread(): ActionUpdateThread {
return ActionUpdateThread.BGT
}
override fun update(event: AnActionEvent) {
event.presentation.isEnabledAndVisible = event.project != null
}
override fun actionPerformed(event: AnActionEvent) {
val project = event.project ?: return
Messages.showInfoMessage(project, "Current project: ${project.name}", "Project Info")
}
}
注册到菜单¶
<actions>
<action
id="com.example.myplugin.ShowProjectInfoAction"
class="com.example.myplugin.ShowProjectInfoAction"
text="Show Project Info"
description="Show information about the current project">
<add-to-group group-id="ToolsMenu" anchor="first"/>
</action>
</actions>
update() 与 actionPerformed()¶
update() 控制 Action 是否可见、是否可用、显示文本和图标。它会被频繁调用,必须非常快。
适合在 update() 做:
- 判断是否有打开的项目。
- 判断当前编辑器、文件类型、选择区是否满足条件。
- 修改
Presentation的可见性、可用性、文本。
不适合在 update() 做:
- 扫描整个项目。
- 访问网络或磁盘重操作。
- 复杂索引查询。
- 修改 PSI、VFS 或项目模型。
actionPerformed() 是用户真正触发后的执行逻辑。耗时工作应放入后台任务,再回到 EDT 更新 UI。
getActionUpdateThread()¶
面向 2022.3 及之后平台时,Action 需要声明 update() 运行线程:
ActionUpdateThread.BGT:后台线程,适合读取 PSI/VFS/项目数据。ActionUpdateThread.EDT:UI 线程,适合访问 Swing 组件。
默认优先考虑 BGT。如果 update() 必须读取 UI 状态,才使用 EDT。
Action 中不要保存项目状态¶
Action 实例生命周期很长,不要在字段中保存 Project、Editor、PsiElement 等上下文对象,否则容易造成内存泄漏。每次调用都从 AnActionEvent 里取当前上下文。
获取上下文数据¶
val project = event.project
val editor = event.getData(com.intellij.openapi.actionSystem.CommonDataKeys.EDITOR)
val file = event.getData(com.intellij.openapi.actionSystem.CommonDataKeys.PSI_FILE)
如果某个上下文可选,代码应优雅降级;如果是必需条件,在 update() 中禁用 Action。