23 组件生命周期:aboutToAppear、aboutToDisappear、onPageShow

23 组件生命周期:aboutToAppear、aboutToDisappear、onPageShow
23 组件生命周期aboutToAppear、aboutToDisappear、onPageShow前言图23 组件生命周期aboutToAppear、aboutToDisappear、onPageShow 运行效果截图HarmonyOS NEXT每个 ArkUI 组件从创建到销毁都有一个明确的生命周期。了解生命周期方法的调用时机可以帮助开发者在正确的时机做正确的事——在创建时加载数据、在显示时刷新界面、在销毁时释放资源。本文以鹿鹿·笔迹心理分析项目中多个页面的生命周期实践为例深入解析 ArkUI 组件生命周期的调用顺序、使用场景和最佳实践。鸿蒙官方·组件生命周期developer.huawei.com项目源码仓库harmony-app GitHub图ArkUI 组件从创建到销毁的完整生命周期时序——包括 Entry 专属的 onPageShow/onPageHide子组件Entry 页面组件页面路由子组件Entry 页面组件页面路由初始化数据、触发动画每次页面可见时触发释放资源、清理定时器pushUrl() 跳转aboutToAppear()创建子组件aboutToAppear()build() 首次渲染onPageShow()popUrl() 返回上页onPageHide()销毁子组件aboutToDisappear()aboutToDisappear()一、ArkUI 组件生命周期总览1.1 生命周期方法ArkUI 组件Component提供了以下生命周期方法方法调用时机用途是否所有组件都有aboutToAppear组件创建后、build() 前初始化数据、触发入场动画✅ 所有组件build()组件首次渲染构建 UI 描述✅ 必须实现aboutToDisappear组件销毁前清理定时器、释放资源✅ 所有组件onPageShow页面显示时每次刷新页面数据❌ 仅 Entry 组件onPageHide页面隐藏时暂停操作❌ 仅 Entry 组件1.2 生命周期时序一个典型页面的生命周期调用顺序页面路由跳转 ↓ aboutToAppear ← ① 组件创建初始化数据 ↓ build() ← ② 首次构建 UI ↓ onPageShow ← ③ 页面可见每次返回页面都会触发 ↓ 用户使用页面 ↓ 路由跳转/返回 ↓ onPageHide ← ④ 页面不可见 ↓ aboutToDisappear ← ⑤ 组件销毁清理资源关键区别aboutToAppear在组件首次创建时调用一次onPageShow在页面每次显示时调用包括从其他页面返回时。二、aboutToAppear组件初始化2.1 数据加载[ReportDetailPage.ets](file:///Users/fiona/Downloads/bijixinli/harmony-app/entry/src/main/ets/pages/ReportDetailPage.ets) 在aboutToAppear中完成数据初始化aboutToAppear(){// ① 初始化页面时间戳constnownewDate()this.srcDate${now.getMonth()1}/${now.getDate().toString().padStart(2,0)}this.currentTime${now.getHours().toString().padStart(2,0)}:${now.getMinutes().toString().padStart(2,0)}// ② 加载报告数据异步this.loadReport()}[HomePage.ets](file:///Users/fiona/Downloads/bijixinli/harmony-app/entry/src/main/ets/pages/HomePage.ets) 在 aboutToAppear 中做更复杂的初始化aboutToAppear():void{// ① 读取 AppStorage 全局数据constname:string|undefinedAppStorage.getstring(user_name)if(name)this.userNamename// ② 异步加载数据this.loadRecent()this.checkCoupleStatus()// ③ 初始化问候语constnow:DatenewDate()consth:numbernow.getHours()this.greetingPeriodh12?早安:h18?下午好:晚上好this.greetingDate${now.getMonth()1}月${now.getDate()}日this.currentTime${h.toString().padStart(2,0)}:${now.getMinutes().toString().padStart(2,0)}// ④ 触发入场动画setTimeout 确保 build() 已完成setTimeout(()this.startEntranceAnimation(),50)}2.2 动画触发Canvas 动画组件在aboutToAppear中触发animateTo// HandwritingRadar.etsaboutToAppear():void{animateTo({duration:AppAnimations.RADAR_DRAW_DURATION,curve:AppAnimations.CURVE_SMOOTH},(){this.drawProgress1// 触发 Watch → draw() 重绘})}2.3 定时器启动[EmptyState.ets](file:///Users/fiona/Downloads/bijixinli/harmony-app/entry/src/main/ets/common/components/EmptyState.ets) 在aboutToAppear中启动呼吸脉冲定时器aboutToAppear():void{// 入场动画animateTo({duration:600,curve:Curve.FastOutSlowIn},(){this.illustrationOpacity1this.illustrationOffset0})// 启动呼吸脉冲this.pulseTimersetInterval((){animateTo({duration:800,curve:Curve.EaseOut},(){this.pulseScalethis.pulseScale1.05?1:1.06})},1600)}2.4 aboutToAppear 中的常见操作操作代码模式适用场景示例页面读取 AppStorageAppStorage.getT(key)全局数据读取HomePage异步数据加载this.loadData()(async)DB/网络请求ReportDetailPage动画触发animateTo({...}, () { state value })入场动画HandwritingRadar定时器启动this.timer setInterval(...)循环动画EmptyState状态初始化this.state defaultValue数据准备CapturePage提示aboutToAppear中无法获取组件在 UI 中的尺寸此时build()尚未执行。需要尺寸信息应在build()的onReady或onAreaChange中获取。三、aboutToDisappear资源清理3.1 定时器清理使用setInterval/setTimeout的组件必须在aboutToDisappear中清理// EmptyState.etsprivatepulseTimer:number-1aboutToDisappear():void{if(this.pulseTimer!-1){clearInterval(this.pulseTimer)this.pulseTimer-1}}3.2 相机资源释放[CapturePage.ets](file:///Users/fiona/Downloads/bijixinli/harmony-app/entry/src/main/ets/pages/CapturePage.ets) 在页面销毁时释放相机资源// CapturePage 中的资源释放方法privatereleaseCamera(){try{if(this.captureSession){this.captureSession.release()// 释放拍照会话}if(this.cameraInput){this.cameraInput.close()// 关闭相机输入}}catch(error){hilog.error(0x0000,TAG,释放相机资源失败: %{public}s,JSON.stringify(error))}}3.3 应该清理的资源类型资源类型清理方式未清理的后果setIntervalclearInterval()内存泄漏、页面销毁后仍在执行setTimeoutclearTimeout()页面销毁后回调仍然触发相机资源.release()/.close()相机被占用其他应用无法使用文件句柄.close()文件锁、文件描述符泄漏事件监听.off()/.unsubscribe()内存泄漏、重复回调关键原则任何在aboutToAppear中打开的资源都必须在aboutToDisappear中关闭。四、onPageShow页面刷新4.1 每次显示时刷新数据onPageShow在页面每次显示给用户时都会调用——包括首次加载、从其他页面返回、从后台切换回前台// HomePage.etsonPageShow():void{// 每次回到首页都刷新数据this.loadRecent()this.checkCoupleStatus()}4.2 刷新场景对比场景触发方法是否需要刷新首次进入页面aboutToAppear→onPageShow✅从子页面返回onPageShowaboutToAppear 不触发✅切换 Tab 回到页面onPageShow✅从后台回到前台onPageShow视情况屏幕旋转重建组件 → 完整生命周期✅4.3 onPageShow vs aboutToAppearEntryComponentstruct HomePage{recentItems:RecentItem[][]// ① 组件首次创建时触发aboutToAppear():void{// 只做一次的事情初始化问候语、启动动画this.greetingPeriod下午好this.loadRecent()// 首次加载数据setTimeout(()this.startEntranceAnimation(),50)}// ② 每次页面可见时触发返回时也会onPageShow():void{// 每次刷新数据因为可能在子页面创建了新报告this.loadRecent()this.checkCoupleStatus()}}区别总结对比aboutToAppearonPageShow触发次数组件整个生命周期只触发 1 次页面每次显示都触发适用操作初始化、入场动画数据刷新、状态同步适用组件Entry 和 Component仅 Entry 页面组件从后台返回❌ 不触发✅ 触发五、生命周期在 Canvas 组件中的应用5.1 Canvas 组件的 onReadyCanvas 组件有一个不同于一般组件的特殊回调——onReady在 Canvas 上下文就绪后调用Componentexportstruct HandwritingRadar{privatecontext:CanvasRenderingContext2DnewCanvasRenderingContext2D(newRenderingContextSettings(true))aboutToAppear():void{// ① 触发动画此时 Canvas 尚未就绪不能绘图animateTo({duration:800},(){this.drawProgress1})}onDrawProgressChange():void{// ② Watch 回调 → 绘图此时 Canvas 已经就绪this.draw()}build(){Canvas(this.context).width(this.radarSize).height(this.radarSize).onReady((){// ③ Canvas 上下文就绪 → 首次绘图this.draw()})}}完整的 Canvas 生命周期时序aboutToAppear→ 触发animateTo仅改变 State不绘图build()→ Canvas 组件创建Canvas.onReady→ Canvas 绘图上下文就绪 → 首次draw()animateTo持续更新drawProgress→Watch持续调用draw()aboutToDisappear→ 组件销毁5.2 页面转场动画页面级的转场动画通过pageTransition方法配置// CapturePage.etspageTransition(){PageTransitionEnter({duration:350,curve:Curve.FastOutSlowIn}).slide(SlideEffect.Right)// 从右侧滑入PageTransitionExit({duration:300,curve:Curve.FastOutSlowIn}).slide(SlideEffect.Right)// 向右侧滑出}六、生命周期的调试技巧6.1 使用 hilog 追踪生命周期constTAGHomePageaboutToAppear():void{hilog.info(0x0000,TAG,aboutToAppear)// ...}onPageShow():void{hilog.info(0x0000,TAG,onPageShow)// ...}aboutToDisappear():void{hilog.info(0x0000,TAG,aboutToDisappear)// ...}6.2 生命周期调用堆栈示例// 打开 App → 首页 [HomePage] aboutToAppear [HomePage] build [HomePage] onPageShow // 跳转到拍照页 [HomePage] onPageHide [CapturePage] aboutToAppear [CapturePage] build [CapturePage] onPageShow // 拍照后返回首页 [CapturePage] aboutToDisappear [HomePage] onPageShow ← 注意没有 aboutToAppear // 关闭 App [HomePage] aboutToDisappear七、生命周期最佳实践清单7.1 检查清单在编写每个组件时检查以下问题问题应该在哪个生命周期处理需要加载数据吗aboutToAppear首次 /onPageShow每次需要入场动画吗aboutToAppear使用了 setInterval 吗启动aboutToAppear/ 清理aboutToDisappear使用了相机/传感器吗初始化aboutToAppear/ 释放aboutToDisappear返回时需要刷新数据吗onPageShow需要在 Canvas 上绘图吗onReady中首次绘制Watch中更新7.2 常见错误// ❌ 错误在 aboutToAppear 中执行异步操作但没处理竞态aboutToAppear():void{this.loadData()// 异步可能组件已销毁才返回}// ✅ 正确使用标志位防止销毁后更新状态privateisActive:booleanfalseaboutToAppear():void{this.isActivetruethis.loadData()}aboutToDisappear():void{this.isActivefalse}privateasyncloadData():Promisevoid{constdataawaitfetchData()if(this.isActive){this.stateDatadata// 组件还在才更新}}八、EntryAbility 生命周期8.1 UIAbility 生命周期项目入口 [EntryAbility.ets](file:///Users/fiona/Downloads/bijixinli/harmony-app/entry/src/main/ets/EntryAbility.ets) 使用应用级生命周期方法exportdefaultclassEntryAbilityextendsUIAbility{// 应用创建onCreate(want:Want,launchParam:AbilityConstant.LaunchParam):void{hilog.info(0x0000,HandwritingAnalysis,Ability onCreate)}// 应用销毁onDestroy():void{hilog.info(0x0000,HandwritingAnalysis,Ability onDestroy)}// 窗口创建加载页面、初始化DBonWindowStageCreate(windowStage:window.WindowStage):void{// 初始化本地数据库DatabaseService.getInstance().init(this.context).then(async(){constuserawaitUserDao.ensureLocalUser(鹿鹿用户)AppStorage.setOrCreatenumber(user_id,user.id??1)AppStorage.setOrCreatestring(user_name,user.name)})// 加载首屏页面windowStage.loadContent(pages/LoginPage,...)}// 窗口销毁onWindowStageDestroy():void{...}// 切到前台onForeground():void{...}// 切到后台onBackground():void{...}}8.2 两级生命周期对比层级入口用途示例应用级UIAbility方法全局初始化、数据库onCreate/onWindowStageCreate页面级Entry组件方法页面加载、刷新aboutToAppear/onPageShow组件级Component方法组件初始化、清理aboutToAppear/aboutToDisappear总结ArkUI 组件生命周期是管理数据、动画和资源的核心工具。本文通过项目中的实际代码案例总结了各生命周期方法的调用时机和使用场景aboutToAppear组件初始化——加载数据、触发动画、启动定时器aboutToDisappear资源清理——清除定时器、释放相机、关闭文件句柄onPageShow页面刷新——每次显示时重新加载数据onPageHide页面离开——暂停动画或资源消耗操作onReadyCanvas 就绪——首次绘制核心原则成对出现——aboutToAppear 中打开的资源在 aboutToDisappear 中关闭aboutToAppear 中加载的数据在 onPageShow 中刷新。下一篇文章将进入第五模块数据持久化——RDB 关系型数据库从鸿蒙原生数据库的使用开始讲解。如果这篇文章对你有帮助欢迎点赞、收藏⭐、关注你的支持是我持续创作的动力参考资源ArkUI 组件生命周期aboutToAppear 参考onPageShow 页面显示UIAbility 生命周期[HomePage 项目源码](file:///Users/fiona/Downloads/bijixinli/harmony-app/entry/src/main/ets/pages/HomePage.ets)[CapturePage 项目源码](file:///Users/fiona/Downloads/bijixinli/harmony-app/entry/src/main/ets/pages/CapturePage.ets)[EmptyState 组件源码](file:///Users/fiona/Downloads/bijixinli/harmony-app/entry/src/main/ets/common/components/EmptyState.ets)[EntryAbility 项目源码](file:///Users/fiona/Downloads/bijixinli/harmony-app/entry/src/main/ets/EntryAbility.ets)HarmonyOS 官方示例