激活和销毁函数什么时候调用,激活里能不能做重活?
结论
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。