Dart VM 扩展开发
适用于支持
dartVmDevTool扩展点的 FlutterX 版本
FlutterX 的 Dart VM ToolWindow 通过 shop.itbug.FlutterCheckVersionX.dartVmDevTool 扩展点开放 tab 能力。内置的 Vm、Memory、Http Monitor、Logging、Provider、Shared Preferences、Hive CE、Drift DB 都使用同一个扩展点注册,第三方插件也可以用同样的方式加入自己的 Dart VM DevTools。
接入方式
第三方插件需要先依赖 FlutterX,然后在 FlutterX 的命名空间下注册 dartVmDevTool。
<depends>shop.itbug.FlutterCheckVersionX</depends>
<extensions defaultExtensionNs="shop.itbug.FlutterCheckVersionX">
<dartVmDevTool
id="myTool"
implementation="com.example.MyDartVmDevTool"
descriptionKey="my.tool.description"
order="after hive"/>
</extensions>
扩展属性
| 属性 | 是否必填 | 说明 |
|---|---|---|
id |
是 | 稳定的 tab ID。FlutterX 会用它保存用户隐藏 tab 的设置,发布后不建议修改。 |
implementation |
是 | 实现 shop.itbug.flutterx.api.vm.DartVmDevToolExtension 的类。 |
descriptionKey |
否 | 多语言描述 key。FlutterX 会从贡献插件的 resource bundle 读取文本,并显示在 Dart VM 设置页里。 |
order |
否 | IntelliJ 扩展排序规则,例如 first、last、after hive、before drift。 |
如果没有配置 descriptionKey,或者 key 在 resource bundle 中不存在,设置页不会显示描述文本。
实现扩展类
扩展类建议保持无状态,不要在构造函数里执行耗时逻辑。真正的 UI 和 VM Service 访问应放到 createComponent 返回的组件生命周期里处理。
package com.example
import com.intellij.openapi.project.Project
import shop.itbug.flutterx.api.vm.DartVmDevToolContext
import shop.itbug.flutterx.api.vm.DartVmDevToolExtension
import java.awt.BorderLayout
import javax.swing.JComponent
import javax.swing.JLabel
import javax.swing.JPanel
class MyDartVmDevTool : DartVmDevToolExtension {
override fun getTabTitle(project: Project): String = "My Tool"
override fun isAvailable(context: DartVmDevToolContext): Boolean {
return true
}
override fun createComponent(context: DartVmDevToolContext): JComponent {
return JPanel(BorderLayout()).apply {
add(JLabel("My FlutterX Dart VM tool"), BorderLayout.CENTER)
}
}
}
createComponent 返回的是 Swing JComponent。FlutterX 不把 Compose 或 Jewel 类型暴露给第三方插件,这样可以减少 Kotlin、Compose、Jewel 版本兼容问题。
读取运行中的 Flutter 应用
DartVmDevToolContext 提供当前项目、ToolWindow 和运行中的 Flutter 应用状态。
interface DartVmDevToolContext {
val project: Project
val toolWindow: ToolWindow
val runningApps: StateFlow<List<DartVmApp>>
}
runningApps 是动态状态。如果用户先打开 FlutterX Dart VM ToolWindow,再启动 Flutter 应用,扩展组件需要订阅 context.runningApps 才能收到更新。
interface DartVmApp {
val appId: String
val vmUrl: String
val deviceId: String
val mode: String
val vmService: VmService
}
可以通过 DartVmApp.vmService 调用 Dart VM Service RPC。VM 调用可能耗时或失败,不要阻塞 EDT。
多语言描述
如果想在 Dart VM 设置页展示 tab 描述,可以配置 descriptionKey,并在第三方插件自己的 resource bundle 里提供文本。
<idea-plugin>
<resource-bundle>messages.MyPluginBundle</resource-bundle>
<depends>shop.itbug.FlutterCheckVersionX</depends>
<extensions defaultExtensionNs="shop.itbug.FlutterCheckVersionX">
<dartVmDevTool
id="myTool"
implementation="com.example.MyDartVmDevTool"
descriptionKey="my.tool.description"
order="after hive"/>
</extensions>
</idea-plugin>
用户显示和隐藏 tab
FlutterX 会在 Dart VM 设置页自动列出所有已注册的 Dart VM tab,包括第三方插件贡献的 tab。tab 默认显示,用户取消勾选后不会再显示。
隐藏设置通过扩展的 id 保存。已经发布的第三方插件不要随意修改 id,否则用户之前的显示或隐藏偏好会失效。
注意事项
- v1 不支持第三方插件安装或卸载后即时刷新已经打开的 Dart VM tab,通常需要重新打开 ToolWindow 或重启 IDE。
- 某个扩展创建组件失败时,FlutterX 会跳过该 tab,并继续加载其他 tab。
- 使用
isAvailable可以按项目、依赖或运行状态决定是否显示 tab。 - 组件需要自己处理释放逻辑,避免后台协程、监听器或 VM Service 订阅泄漏。
验证
开发第三方扩展时建议验证以下场景:
./gradlew compileKotlin能通过。./gradlew verifyPluginStructure能通过。- 打开 FlutterX Dart VM 后能看到第三方 tab。
order="after hive"等排序规则生效。- 先打开 ToolWindow 再运行 Flutter 应用,订阅
runningApps的 UI 能正常刷新。 - 在 Dart VM 设置页取消勾选后,tab 不再显示;重新勾选后恢复显示。