跳到主要内容

激活和销毁函数什么时候调用,激活里能不能做重活?

结论​

activate 在插件第一次被某个激活事件触发时调用,整个宿主进程里只会成功执行一次。deactivate 在插件被禁用、卸载、窗口重载或退出时调用。激活函数里只做注册和轻量初始化,重活放到后台,并且不要阻塞返回。

展开​

扩展宿主启动后,并不会立刻执行所有插件。它先读 package.json,等激活事件发生,才加载入口并调用:

export function activate(context: vscode.ExtensionContext) {
// 注册命令、监听器、视图
}

export function deactivate() {
// 可选。订阅放进 context.subscriptions 时,多数资源会自动释放
}

常见触发包括:用户执行了你贡献的命令、打开了某种语言的文件、展开了你的侧边栏视图、工作区里出现了某个文件。

activate 可以返回 Thenable。宿主会等这个 Promise 完成,才认为插件激活结束。如果在里面同步读大文件、起语言服务器并空等握手、或者做全量扫描,激活耗时会被记到「Running Extensions」里,拖慢启动,也会堵住这个扩展宿主的事件循环。

推荐做法:

  • 同步完成命令、语言功能、视图的注册。
  • 耗时工作用 void startServer() 这样的方式丢到后台,失败再写日志、弹通知。
  • 需要进度时用 window.withProgress,不要让 activate 一直 pending。

deactivate 没有 context 参数,时间也很短。适合停语言服务器、刷最后一次状态。监听器、定时器、Webview 更应该在激活时推进 context.subscriptions,由宿主统一 dispose。

容易讲错的点​

  • 激活不是「安装时」也不是「每次执行命令时」。安装只是下载,第一次命中激活事件才加载。
  • 同一个宿主里 activate 不会因为再次执行命令而重入。命令回调会反复执行,激活函数不会。
  • 插件在远程窗口可能跑两份(界面宿主和工作区宿主)。每一份有自己的一次 activate。