UIAbility 与 WindowStage:窗口创建、加载、销毁的完整链路 UIAbility 与 WindowStage窗口创建、加载、销毁的完整链路在 Stage 模型里UIAbility负责应用组件生命周期WindowStage负责承载页面窗口。很多窗口问题表面看是页面白屏、重复加载、销毁后回调还在执行本质都是 Ability 和窗口职责没有拆开。这篇按真实启动过程拆解Ability 创建、窗口创建、页面加载、窗口销毁、资源释放每一步都说明代码应该放在哪里。1. UIAbility 不等于页面容器UIAbility是系统调度组件实例的入口WindowStage才是页面加载和窗口管理的直接对象。把页面加载写进onCreate短期可能还能跑但窗口未就绪时就容易出现时序问题。exportdefaultclassEntryAbilityextendsUIAbility{onCreate():void{AbilityBootRecorder.mark(abilityCreate);}onWindowStageCreate(windowStage:window.WindowStage):void{AbilityBootRecorder.mark(windowCreate);WindowBootstrap.loadMain(windowStage);}}代码解释onCreate只记录 Ability 已创建不做页面加载。页面加载交给onWindowStageCreate符合系统窗口创建顺序。WindowBootstrap独立出来后测试和复用会更简单。2. 页面加载要处理失败分支很多 Demo 只写loadContent(pages/Index)不处理错误。实际项目中页面路径错误、资源异常、初始化失败都可能导致白屏。import{window}fromkit.ArkUI;import{hilog}fromkit.PerformanceAnalysisKit;constDOMAIN0x20260702;exportclassWindowBootstrap{staticloadMain(windowStage:window.WindowStage):void{windowStage.loadContent(pages/Index,(error){if(error.code){hilog.error(DOMAIN,WindowBootstrap,load Index failed%{public}d,error.code);WindowBootstrap.loadFallback(windowStage);return;}hilog.info(DOMAIN,WindowBootstrap,Index loaded);});}privatestaticloadFallback(windowStage:window.WindowStage):void{windowStage.loadContent(pages/ErrorPage);}}代码解释主页面加载失败时给用户一个错误页比白屏更可控。日志记录错误码方便定位是路径问题还是资源问题。兜底页要尽量轻量不依赖复杂业务初始化。3. 启动任务不要阻塞窗口加载用户感知的是首屏出现速度。数据库预热、远程配置、埋点初始化不应该全部挡在loadContent前面。exportclassStartupTaskRunner{staticasyncrunAfterFirstFrame():Promisevoid{awaitPromise.allSettled([RemoteConfigService.load(),AnalyticsService.prepare(),CacheWarmService.prepareHomeData()]);}}exportclassWindowBootstrap{staticloadMain(windowStage:window.WindowStage):void{windowStage.loadContent(pages/Index,(error){if(!error.code){StartupTaskRunner.runAfterFirstFrame();}});}}代码解释首屏加载成功后再跑非关键初始化减少冷启动等待。Promise.allSettled避免一个非关键任务失败影响其他任务。关键初始化和非关键初始化要分组不能全部塞进启动入口。4. 保存 WindowStage 引用要谨慎有些业务需要操作窗口例如设置亮度、沉浸式、窗口属性。可以持有当前WindowStage但必须在销毁时清理避免引用过期。exportclassWindowStageHolder{privatestaticcurrent?:window.WindowStage;staticattach(stage:window.WindowStage):void{WindowStageHolder.currentstage;}staticdetach():void{WindowStageHolder.currentundefined;}staticget():window.WindowStage|undefined{returnWindowStageHolder.current;}}代码解释attach在窗口创建时调用detach在窗口销毁时调用。调用方必须处理undefined不能假设窗口一直存在。不建议把WindowStage到处传递统一 holder 更便于治理。5. onWindowStageDestroy 是释放资源的边界页面销毁不等于 Ability 销毁窗口销毁也不等于进程退出。窗口相关监听、临时缓存、页面级任务应在onWindowStageDestroy释放。exportdefaultclassEntryAbilityextendsUIAbility{onWindowStageDestroy():void{WindowStageHolder.detach();WindowEventBus.clear();PageTaskRegistry.cancelAll();hilog.info(DOMAIN,EntryAbility,window destroyed);}}代码解释窗口引用、事件监听、页面任务都属于窗口生命周期资源。清理动作集中在销毁回调里比页面各自释放更可靠。日志能帮助判断白屏或回调异常是否来自旧窗口。6. 窗口事件要统一订阅和取消窗口尺寸变化、焦点变化、前后台变化都可能影响页面布局。不要让多个页面直接订阅底层窗口事件否则很难确保取消。exportclassWindowEventBus{privatestaticlisteners:Array()void[];staticaddCleaner(cleaner:()void):void{WindowEventBus.listeners.push(cleaner);}staticclear():void{for(constcleanerofWindowEventBus.listeners){cleaner();}WindowEventBus.listeners[];}}代码解释订阅窗口事件时同步登记取消函数。窗口销毁时统一执行避免漏取消。如果项目有多个窗口应按窗口 id 分组管理。7. 加载顺序要可观测启动白屏最怕“感觉慢”。记录 Ability 创建、窗口创建、页面加载完成、首个业务数据返回四个时间点能快速判断瓶颈。exportclassAbilityBootRecorder{privatestaticmarksnewMapstring,number();staticmark(name:string):void{AbilityBootRecorder.marks.set(name,Date.now());}staticduration(start:string,end:string):number{constsAbilityBootRecorder.marks.get(start)??0;consteAbilityBootRecorder.marks.get(end)??0;returnes?e-s:0;}}代码解释mark记录关键节点时间。duration计算两个节点间耗时用于日志和性能看板。建议只记录阶段耗时不要在启动链路里做复杂计算。8. 窗口加载失败的兜底页也要能退出错误页不能只是提示失败还要提供重试、退出或反馈入口。否则用户只能杀进程。exportclassWindowRecoverAction{staticretry(windowStage:window.WindowStage):void{WindowBootstrap.loadMain(windowStage);}staticreport(errorCode:number):void{FeedbackService.open({scene:window_load_failed,errorCode:String(errorCode)});}}代码解释重试逻辑复用主加载流程不再复制一套。反馈时带上错误场景和错误码客服或日志平台才有信息可查。如果兜底页本身也加载失败应记录严重错误并退出当前 Ability。9. 验收清单检查项通过标准onCreate不直接加载页面onWindowStageCreate负责主页面加载和失败处理非关键初始化不阻塞首屏WindowStage引用创建时保存销毁时释放错误页可重试、可反馈、可退出10. 小结UIAbility管组件生命周期WindowStage管窗口和页面承载。把这两层拆清楚后启动白屏、重复加载、销毁后回调这类问题都会更容易定位。工程上建议保留WindowBootstrap、WindowStageHolder、AbilityBootRecorder三个基础设施类让窗口链路可读、可测、可恢复。