2.4 装配时序:启动、窗口与退出的生命周期


图纸章的最后一刀是通电:从双击图标到进程退出,Tauri 按什么时序驱动你的代码。本节给出完整的生命周期地图,并回答一个实操问题——初始化数据库、恢复窗口状态、弹出确认框这些代码,各自该挂在哪个钩子上。挂错时序的初始化,是"启动偶尔白屏""退出不弹确认"这类疑难杂症的根源。

通电:一张状态图看全程

状态图上有两个"你的代码可以进场"的窗口:Setup 钩子(页面加载前)与运行中(命令、事件、窗口事件回调里)。大多数初始化错误就是把该在 Setup 做的事放到了运行中,或反之。

Setup 钩子:页面加载前的黄金时段

pub fn run() { tauri::Builder::default() .plugin(tauri_plugin_store::Builder::new().build()) .invoke_handler(tauri::generate_handler![add_note, list_notes]) .setup(|app| { // 此时窗口已按配置创建,但页面未必加载完 if let Some(main) = app.get_webview_window("main") { let _ = main.set_title("随身笔记"); } // 后台任务不阻塞启动:交给异步运行时 tauri::async_runtime::spawn(async move { if let Err(e) = open_database().await { eprintln!("数据库初始化失败: {e}"); } }); Ok(()) }) .run(tauri::generate_context!()) .expect("failed to run"); }

Setup 里做三件事最合适:同步初始化(注册菜单、恢复窗口状态插件的数据)、改窗口属性(标题、尺寸微调)、派发后台任务(数据库连接、文件索引——注意用 async_runtime::spawn 扔给运行时,不要在 Setup 里直接 await,否则窗口迟迟不出来)。反过来,别在 Setup 里做重活是启动性能的第一守则,第 8 章会量化这件事。

运行中:命令、事件与窗口事件

页面加载完成后进入稳态,命令与事件按 2.2 节的传送带往返。这一阶段还有一个容易被忽视的事件源:窗口事件。用户拖动、缩放、聚焦、点关闭按钮,都从这里来:

.on_window_event(|window, event| match event { tauri::WindowEvent::CloseRequested { api, .. } => { // 有未保存内容则拦截关闭,改为询问 if has_unsaved(window.label()) { api.prevent_close(); confirm_exit(window.app_handle(), window.label()); } } tauri::WindowEvent::Resized { .. } => { // 防抖后持久化窗口尺寸 schedule_save_window_state(window.label()); } _ => {} })

CloseRequested 是"关闭拦截"的标准挂点:prevent_close 让本次关闭作废,应用转入询问流程——弹原生对话框或发事件让前端弹自己的保存确认 UI。托盘常驻类应用在这里分流出"关闭窗口但留在托盘"的语义(第 7 章托盘节有完整实现)。

退出:RunEvent 与清理的边界

所有窗口都关了,进程走到退出。想在退出前清理(保存设置、关闭数据库连接、给更新检查留遗言),挂 RunEvent::ExitRequestedExit

.build(tauri::generate_context!()) .expect("failed to build") .run(|app, event| match event { tauri::RunEvent::ExitRequested { code, .. } => { if code.is_none() { // code 为空表示还有窗口在阻止退出,可在此决定是否强制 } flush_pending_writes(); } tauri::RunEvent::Exit { .. } => { // 最后的清理点,尽量只做快操作 close_database(); } _ => {} })

退出清理的两条纪律:只做快操作——退出路径上的用户耐心以毫秒计,慢活应该在运行中增量完成;幂等——崩溃场景下清理函数可能没机会执行,所以运行中就要把关键数据落盘,退出清理只是兜底而不是唯一保障。

时序排错的通用套路

遇到"启动白屏""初始化偶发失败",按三层顺序排查:前端在 onLoad 里 invoke 的命令,如果该命令依赖 Setup 里初始化的状态,就是时序倒挂——要么把初始化挪进 Setup 同步段,要么命令侧返回"未就绪"让前端重试。窗口事件没触发,先确认 Builder 链上挂了 on_window_event 且在最外层 run 上(而不是某个窗口对象上)注册。记住原则:Setup 里同步可慢则派发、前端入口不假设芯已就绪、退出清理幂等——三条覆盖九成生命周期坑。

本节要点回顾

  • 生命周期主干:进程启动 → Builder 装配 → Setup → 窗口创建 → 页面加载 → 运行中 → 关闭拦截 → 退出;
  • Setup 的分工:同步初始化、窗口属性调整、派发后台任务;重活必用异步运行时承接;
  • 关闭拦截CloseRequestedprevent_close,托盘常驻应用在此分流;
  • 退出清理挂 RunEvent,纪律是快操作加幂等,关键数据运行中就落盘;
  • 排错套路:前端调用与芯初始化的时序倒挂是启动期 bug 的头号模式。

第 2 章图纸收卷:三层、传送带、壳体差异、时序全图都在手上。下一章开工备料——把环境装齐,把脚手架跑通,把装配说明书逐项读懂。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U