保姆级教程:HarmonyOS6 应用窗口与生命周期的 8 个关键时刻
文章目录前言一、UIAbility 生命周期概述1.1 什么是生命周期回调1.2 生命周期的完整流程二、onCreate 与 onDestroyAbility 的出生和死亡2.1 onCreateAbility 出生那一刻2.2 onDestroyAbility 的最后告别三、onWindowStageCreate 与 onWindowStageDestroyUI 舞台的搭建与拆除3.1 什么是 WindowStage3.2 onWindowStageCreate搭舞台、放内容3.3 onWindowStageWillDestroy 和 onWindowStageDestroy拆舞台3.4 WindowStage 事件类型详解四、onForeground 和 onBackground前台与后台的切换4.1 onForeground重新开门迎客4.2 onBackground打烊了释放资源五、onNewWant同一个 Ability 被多次唤起5.1 什么是 onNewWant六、EntryAbility 完整代码总结八个回调的职责速查实践中的 5 个关键原则前言你有没有想过一个手机 App 从点击图标到完全退出到底经历了哪些人生阶段就像一个人从出生、求学、工作、退休到最终离开每个阶段都有不同的任务和注意事项。HarmonyOS 的 UIAbility 生命周期就是这个人生规划的完整剧本。在 HarmonyOS 中UIAbility是一个非常重要的概念——你可以把它理解为一个拥有 UI 界面的功能模块。每当你打开一个页面背后可能就有一个 UIAbility 在工作。理解它的生命周期能帮助你正确管理资源比如音乐播放、图片加载避免内存泄漏让你的 App 更流畅、更省电。本文将带你一步一步搞清楚 UIAbility 的八个生命周期回调以及WindowStage 窗口舞台事件的完整机制。学完之后你将能够写出专业的 Ability 代码在每个阶段都做正确的事。一、UIAbility 生命周期概述1.1 什么是生命周期回调想象一下你开了一家餐厅。餐厅有不同的状态开业前需要装修准备、营业中接待客人前台、晚上打烊后整理后台、彻底关门时退还设备销毁。每个状态转换时你都需要做一些特定的事情——比如开业前要招聘员工打烊后要关灯。UIAbility 的生命周期回调就是 HarmonyOS 系统在 Ability 状态发生变化时自动调用的一系列函数。开发者在这些函数里写代码系统会在合适的时机帮你执行——就像餐厅管理系统自动在特定时间提醒你该做什么一样。在 HarmonyOS 中UIAbility 有8 个核心生命周期回调回调名称触发时机类比场景onCreateAbility 首次创建时餐厅装修完毕第一次开门onWindowStageCreate窗口舞台UI 加载区创建餐厅摆好桌椅、挂好菜单onForegroundAbility 进入前台可交互餐厅开始营业接待客人onBackgroundAbility 进入后台餐厅打烊不再接待新客人onWindowStageWillDestroy窗口舞台即将销毁餐厅准备重新装修onWindowStageDestroy窗口舞台销毁餐厅拆除桌椅onNewWantAbility 被再次唤起而非新建老客人从后门又进来了onDestroyAbility 最终销毁餐厅彻底关门歇业1.2 生命周期的完整流程下面这张图展示了 UIAbility 从创建到销毁的完整路径。浅蓝色是装修准备阶段浅绿色是正常营业阶段浅红色是关门清算阶段。系统在每次状态转换时都会自动调用对应的回调函数。二、onCreate 与 onDestroyAbility 的出生和死亡2.1 onCreateAbility 出生那一刻大白话说明onCreate就像你搬进新家的第一天。你会做很多一次性的事情买家具、开通水电煤、认识邻居。这些事情只在入住时做一次之后每天回家不需要再做一遍。代码示例import{AbilityConstant,UIAbility,Want}fromkit.AbilityKit;import{window}fromkit.ArkUI;import{hilog}fromkit.PerformanceAnalysisKit;constDOMAIN0x0000;exportdefaultclassEntryAbilityextendsUIAbility{// 保存 windowStage 引用供 onWindowStageWillDestroy 中使用publicwindowStage:window.WindowStage|undefinedundefined;onCreate(want:Want,launchParam:AbilityConstant.LaunchParam):void{// 整个生命周期中只会执行一次的初始化逻辑// 例如初始化成员变量、注册系统事件监听、申请全局资源等hilog.info(DOMAIN,testTag,%{public}s,Ability onCreate);}}参数说明want: Want系统传来的启动意图包含是谁启动了我、从哪里来、携带了哪些参数。类似快递包裹上的收件人信息。launchParam: AbilityConstant.LaunchParam系统给出的启动参数说明本次启动的原因正常启动、异常恢复等。hilog.info华为提供的日志工具用于调试时输出信息方便定位代码执行位置。注意onCreate中不要执行耗时操作如网络请求、大文件读取否则会导致应用启动缓慢影响用户体验。如果确实需要做耗时操作建议放在onForeground之后以异步方式处理。2.2 onDestroyAbility 的最后告别大白话说明onDestroy就像退租房子时要做的事——结清水电费、归还钥匙、清空房间。这些事情必须做好否则会被扣押金系统资源泄漏。代码示例onDestroy():void{// 资源释放与数据保存// 例如停止后台任务、取消网络订阅、保存用户数据到本地hilog.info(DOMAIN,testTag,%{public}s,Ability onDestroy);}要点说明onDestroy是 Ability 生命周期中最后被调用的回调做好收尾工作停止后台任务、取消事件监听、保存未保存的数据。如果你在onCreate中注册了监听器如windowStage.on(...)不要在onDestroy中注销应在onWindowStageWillDestroy中注销原因见第三节。注意onDestroy不保证一定被执行。当系统资源紧张时可能直接杀死进程而不调用该回调。因此重要数据应在onBackground中或定期持久化保存不要完全依赖onDestroy。三、onWindowStageCreate 与 onWindowStageDestroyUI 舞台的搭建与拆除3.1 什么是 WindowStage大白话说明WindowStage就像餐厅里固定的舞台区域。你可以在上面摆桌椅、挂菜单、放装饰品。舞台本身是固定的屏幕区域但上面放的演员UI 页面是可以换的——同一块屏幕区域可以加载不同的页面内容。在代码里WindowStage是一个控制器对象负责管理 Ability 的窗口window和加载的页面内容loadContent。3.2 onWindowStageCreate搭舞台、放内容大白话说明餐厅装修好了现在要摆放桌椅、挂菜单、放装饰品。这就是onWindowStageCreate在做的事——把 UI 元素放到舞台屏幕上去。代码示例onWindowStageCreate(windowStage:window.WindowStage):void{hilog.info(DOMAIN,testTag,%{public}s,Ability onWindowStageCreate);// 保存引用供后续注销监听使用this.windowStagewindowStage;// 订阅窗口舞台事件获焦/失焦、前台/后台切换等try{windowStage.on(windowStageEvent,(data){letstageEventType:window.WindowStageEventTypedata;switch(stageEventType){casewindow.WindowStageEventType.SHOWN:// 切到前台窗口可见hilog.info(DOMAIN,testTag,windowStage foreground.);break;casewindow.WindowStageEventType.ACTIVE:// 获焦可交互hilog.info(DOMAIN,testTag,windowStage active.);break;casewindow.WindowStageEventType.INACTIVE:// 失焦不可交互hilog.info(DOMAIN,testTag,windowStage inactive.);break;casewindow.WindowStageEventType.HIDDEN:// 切到后台窗口不可见hilog.info(DOMAIN,testTag,windowStage background.);break;casewindow.WindowStageEventType.RESUMED:// 前台可交互最终稳定态hilog.info(DOMAIN,testTag,windowStage resumed.);break;casewindow.WindowStageEventType.PAUSED:// 前台不可交互如弹窗遮挡hilog.info(DOMAIN,testTag,windowStage paused.);break;default:break;}});}catch(exception){hilog.error(DOMAIN,testTag,Failed to enable the listener for window stage event changes. Cause: %{public}s,JSON.stringify(exception));}// 加载页面内容最核心的步骤windowStage.loadContent(pages/Index,(err){if(err.code){hilog.error(DOMAIN,testTag,Failed to load the content. Cause: %{public}s,JSON.stringify(err));return;}hilog.info(DOMAIN,testTag,Succeeded in loading the content.);});}要点说明this.windowStage windowStage务必在此处保存引用否则onWindowStageWillDestroy中将无法访问该对象来注销监听。windowStage.on(windowStageEvent, ...)注册监听器用于感知窗口的六种状态变化并在对应状态下做业务处理。windowStage.loadContent(pages/Index, callback)核心步骤将指定路径的 ArkTS 页面加载到屏幕上。回调函数用于处理加载成功或失败的结果。提示loadContent也支持 Promise 异步写法去掉回调参数使用await实际开发中推荐使用 async/await 模式代码更简洁易读。3.3 onWindowStageWillDestroy 和 onWindowStageDestroy拆舞台生活化比喻餐厅要重新装修了工人先来量尺寸、做标记onWindowStageWillDestroy然后才开始拆桌椅、打墙onWindowStageDestroy。两个步骤顺序不能颠倒。// 窗口即将销毁前——注销事件监听此时 windowStage 对象仍然有效onWindowStageWillDestroy(windowStage:window.WindowStage):void{hilog.info(DOMAIN,testTag,%{public}s,Ability onWindowStageWillDestroy);try{if(this.windowStage){this.windowStage.off(windowStageEvent);// 与 on() 对应必须成对出现}}catch(err){hilog.error(DOMAIN,testTag,Failed to disable the listener for windowStageEvent. Code is %{public}d, message is %{public}s,(errasBusinessError).code,(errasBusinessError).message);}}// 窗口彻底销毁——释放 UI 资源onWindowStageDestroy():void{// 在此释放与 UI 相关的资源hilog.info(DOMAIN,testTag,%{public}s,Ability onWindowStageDestroy);}要点说明this.windowStage.off(windowStageEvent)与on()对应注册和注销必须成对出现就像登记入住和退房注销一样。注销监听应放在onWindowStageWillDestroy中而非onDestroy中。因为onDestroy执行时 windowStage 对象已经被销毁此时调用off()可能导致报错或注销失败。两个回调的执行顺序固定先onWindowStageWillDestroy注销监听后onWindowStageDestroy释放 UI 资源。3.4 WindowStage 事件类型详解WindowStageEventType含义实际场景示例SHOWN窗口从隐藏变为可见从其他应用切回本应用HIDDEN窗口从可见变为隐藏打开其他应用本应用退到后台ACTIVE窗口获得焦点可交互点击本应用的任意位置INACTIVE窗口失去焦点不可交互点击系统弹窗、通知栏RESUMED前台可交互的最终稳定状态应用完全可见且可操作PAUSED前台不可交互状态有弹窗遮挡在应用上方时图示解读时序图展示了用户在应用内外进行各种操作时系统如何逐步触发各个回调和窗口事件。从左到右为时间流向箭头表示调用方向。四、onForeground 和 onBackground前台与后台的切换4.1 onForeground重新开门迎客生活化比喻餐厅打烊后突然有 VIP 客人要来服务员需要重新上岗、开灯、热菜——这就是onForeground。后台的 Ability 重新回到前台需要把之前释放的资源重新申请回来。代码示例onForeground():void{// 重新申请系统资源或恢复在 onBackground() 中释放的资源// 例如恢复音乐播放、继续动画、重新申请定位权限hilog.info(DOMAIN,testTag,%{public}s,Ability onForeground);}要点说明onForeground每次 Ability 从后台切换到前台时都会被调用可能触发多次。常见用途恢复onBackground中暂停的任务如继续播放音视频、恢复动画。不要在这里执行过重的操作否则前后台切换时会有明显卡顿感。提示如果应用需要敏感权限如定位、相机建议在onForeground中检查权限状态因为用户随时可能在系统设置中更改权限。4.2 onBackground打烊了释放资源大白话说明餐厅打烊后服务员下班、关灯、关空调把不必要的东西都关掉以节省电力。同理App 退到后台时也要释放那些看不见、用不到的资源。代码示例onBackground():void{// 释放 UI 不可见时无用的资源// 例如停止动画、暂停视频、释放图片缓存、停止 GPS 定位hilog.info(DOMAIN,testTag,%{public}s,Ability onBackground);}要点说明onBackground在 Ability 完全不可见退到后台时触发可能触发多次。重点释放不影响功能但消耗内存/电量的资源正在播放的动画、已加载的大图、不再需要的定位服务等。需要持久化的重要数据应在此处或定期保存不要依赖onDestroy一定被调用。提示很多新手忽略onBackground导致 App 在后台仍然消耗大量资源不仅费电还容易被系统强制终止。建议在开发阶段加上日志验证该回调是否如预期触发。五、onNewWant同一个 Ability 被多次唤起5.1 什么是 onNewWant大白话说明假设你是前台接待员。当第一个客人进来时你开门迎接onCreate。客人暂时离开后第二个客人又来了你不需要重新装修不再调onCreate只需要更新桌牌和菜单onNewWant。onNewWant在 Ability已经存在的情况下被新的启动意图Want再次唤起时触发。与onCreate不同它不会重新初始化整个 Ability只更新数据和 UI 状态。代码示例onNewWant(want:Want,launchParam:AbilityConstant.LaunchParam):void{// 根据新的 Want 更新数据和界面hilog.info(DOMAIN,testTag,%{public}s,Ability onNewWant);// 示例根据 Want 中的 action 参数决定跳转到哪个子页面constactionwant.action??;if(actiondetail){// 跳转详情页通过路由 API}elseif(actionedit){// 跳转编辑页}}要点说明want参数包含了启动方传递的信息比如要显示什么内容、要打开哪个子页面。onNewWant与onCreate互斥冷启动全新创建走onCreate已有实例被再次唤起走onNewWant。如果你的应用支持单实例多入口如分享功能、小组件快捷入口必须实现onNewWant来处理新的启动参数。注意onNewWant触发时onWindowStageCreate不会再次调用。如果需要根据新 Want 加载不同页面应手动调用路由 API如router.pushUrl来切换页面而不是再次调用windowStage.loadContent。六、EntryAbility 完整代码下面是EntryAbility.ets的完整代码涵盖全部八个生命周期回调import{AbilityConstant,UIAbility,Want}fromkit.AbilityKit;import{window}fromkit.ArkUI;import{hilog}fromkit.PerformanceAnalysisKit;import{BusinessError}fromkit.BasicServicesKit;constDOMAIN0x0000;exportdefaultclassEntryAbilityextendsUIAbility{// 保存 windowStage 引用供 onWindowStageWillDestroy 中注销监听使用publicwindowStage:window.WindowStage|undefinedundefined;// ① onCreateAbility 首次创建整个生命周期只调用一次onCreate(want:Want,launchParam:AbilityConstant.LaunchParam):void{hilog.info(DOMAIN,testTag,%{public}s,Ability onCreate);}// ② onWindowStageCreate窗口舞台创建加载 UI 页面onWindowStageCreate(windowStage:window.WindowStage):void{hilog.info(DOMAIN,testTag,%{public}s,Ability onWindowStageCreate);this.windowStagewindowStage;// 订阅窗口事件try{windowStage.on(windowStageEvent,(data){letstageEventType:window.WindowStageEventTypedata;switch(stageEventType){casewindow.WindowStageEventType.SHOWN:hilog.info(DOMAIN,testTag,windowStage foreground.);break;casewindow.WindowStageEventType.ACTIVE:hilog.info(DOMAIN,testTag,windowStage active.);break;casewindow.WindowStageEventType.INACTIVE:hilog.info(DOMAIN,testTag,windowStage inactive.);break;casewindow.WindowStageEventType.HIDDEN:hilog.info(DOMAIN,testTag,windowStage background.);break;casewindow.WindowStageEventType.RESUMED:hilog.info(DOMAIN,testTag,windowStage resumed.);break;casewindow.WindowStageEventType.PAUSED:hilog.info(DOMAIN,testTag,windowStage paused.);break;default:break;}});}catch(exception){hilog.error(DOMAIN,testTag,Failed to enable windowStageEvent listener. Cause: %{public}s,JSON.stringify(exception));}// 加载页面内容必须调用windowStage.loadContent(pages/Index,(err){if(err.code){hilog.error(DOMAIN,testTag,Failed to load content. Cause: %{public}s,JSON.stringify(err));return;}hilog.info(DOMAIN,testTag,Succeeded in loading content.);});}// ③ onForegroundAbility 从后台切换到前台onForeground():void{hilog.info(DOMAIN,testTag,%{public}s,Ability onForeground);}// ④ onBackgroundAbility 进入后台onBackground():void{hilog.info(DOMAIN,testTag,%{public}s,Ability onBackground);}// ⑤ onNewWant同一 Ability 实例被新的 Want 唤起onNewWant(want:Want,launchParam:AbilityConstant.LaunchParam):void{hilog.info(DOMAIN,testTag,%{public}s,Ability onNewWant);}// ⑥ onWindowStageWillDestroy窗口销毁前注销监听windowStage 仍有效onWindowStageWillDestroy(windowStage:window.WindowStage):void{hilog.info(DOMAIN,testTag,%{public}s,Ability onWindowStageWillDestroy);try{if(this.windowStage){this.windowStage.off(windowStageEvent);// 与 on() 对应必须成对}}catch(err){hilog.error(DOMAIN,testTag,Failed to disable windowStageEvent listener. Code: %{public}d, message: %{public}s,(errasBusinessError).code,(errasBusinessError).message);}}// ⑦ onWindowStageDestroy窗口彻底销毁释放 UI 资源onWindowStageDestroy():void{hilog.info(DOMAIN,testTag,%{public}s,Ability onWindowStageDestroy);}// ⑧ onDestroyAbility 最终销毁onDestroy():void{hilog.info(DOMAIN,testTag,%{public}s,Ability onDestroy);}}总结HarmonyOS UIAbility 的八大生命周期回调机制还是比较重要的本篇文章系统的加大白话的方式给大家进行了讲解如有帮助点赞关注哦~八个回调的职责速查分组回调核心职责创建与销毁onCreate一次性初始化成员变量、全局监听创建与销毁onDestroy最终清理停止任务、取消订阅窗口管理onWindowStageCreate保存引用、订阅窗口事件、加载 UI 页面窗口管理onWindowStageWillDestroy注销窗口事件监听windowStage 尚有效窗口管理onWindowStageDestroy释放 UI 资源前后台切换onForeground恢复资源继续播放、恢复动画前后台切换onBackground释放资源暂停播放、停止定位多次唤起onNewWant单实例多入口更新数据和页面状态实践中的 5 个关键原则on和off必须成对在onWindowStageCreate中注册的监听必须在onWindowStageWillDestroy中注销不能放到onDestroy。onCreate不做耗时操作大文件读取、网络请求应放到onForeground之后异步处理。后台必须释放资源onBackground中及时暂停动画、停止定位、释放大图缓存防止被系统杀死。重要数据定期持久化不能只依赖onDestroy保存数据系统可能在未调用onDestroy的情况下终止进程。单实例场景必须实现onNewWant分享入口、小组件跳转等多次唤起场景必须在onNewWant中处理新的 Want 参数。