当前位置: 首页 > news >正文

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(){// ① 初始化页面时间戳constnow=newDate()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|undefined=AppStorage.get<string>('user_name')if(name)this.userName=name// ② 异步加载数据this.loadRecent()this.checkCoupleStatus()// ③ 初始化问候语constnow:Date=newDate()consth:number=now.getHours()this.greetingPeriod=h<12?'早安':h<18?'下午好':'晚上好'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.drawProgress=1// 触发 @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.illustrationOpacity=1this.illustrationOffset=0})// 启动呼吸脉冲this.pulseTimer=setInterval(()=>{animateTo({duration:800,curve:Curve.EaseOut},()=>{this.pulseScale=this.pulseScale>1.05?1:1.06})},1600)}

2.4 aboutToAppear 中的常见操作

操作代码模式适用场景示例页面
读取 AppStorageAppStorage.get<T>('key')全局数据读取HomePage
异步数据加载this.loadData()(async)DB/网络请求ReportDetailPage
动画触发animateTo({...}, () => { state = value })入场动画HandwritingRadar
定时器启动this.timer = setInterval(...)循环动画EmptyState
状态初始化this.state = defaultValue数据准备CapturePage

提示:aboutToAppear中无法获取组件在 UI 中的尺寸(此时build()尚未执行)。需要尺寸信息应在build()onReadyonAreaChange中获取。

三、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 刷新场景对比

场景触发方法是否需要刷新
首次进入页面aboutToAppearonPageShow
从子页面返回onPageShow(aboutToAppear 不触发)
切换 Tab 回到页面onPageShow
从后台回到前台onPageShow视情况
屏幕旋转重建组件 → 完整生命周期

4.3 onPageShow vs aboutToAppear

@Entry@Componentstruct 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 组件的 onReady

Canvas 组件有一个不同于一般组件的特殊回调——onReady,在 Canvas 上下文就绪后调用:

@Componentexportstruct HandwritingRadar{privatecontext:CanvasRenderingContext2D=newCanvasRenderingContext2D(newRenderingContextSettings(true))aboutToAppear():void{// ① 触发动画(此时 Canvas 尚未就绪,不能绘图)animateTo({duration:800},()=>{this.drawProgress=1})}onDrawProgressChange():void{// ② @Watch 回调 → 绘图(此时 Canvas 已经就绪)this.draw()}build(){Canvas(this.context).width(this.radarSize).height(this.radarSize).onReady(()=>{// ③ Canvas 上下文就绪 → 首次绘图this.draw()})}}

完整的 Canvas 生命周期时序:

  1. aboutToAppear→ 触发animateTo(仅改变 @State,不绘图)
  2. build()→ Canvas 组件创建
  3. Canvas.onReady→ Canvas 绘图上下文就绪 → 首次draw()
  4. animateTo持续更新drawProgress@Watch持续调用draw()
  5. 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 追踪生命周期

constTAG='HomePage'aboutToAppear():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:boolean=falseaboutToAppear():void{this.isActive=truethis.loadData()}aboutToDisappear():void{this.isActive=false}privateasyncloadData():Promise<void>{constdata=awaitfetchData()if(this.isActive){this.stateData=data// 组件还在才更新}}

八、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')}// 窗口创建(加载页面、初始化DB)onWindowStageCreate(windowStage:window.WindowStage):void{// 初始化本地数据库DatabaseService.getInstance().init(this.context).then(async()=>{constuser=awaitUserDao.ensureLocalUser('鹿鹿用户')AppStorage.setOrCreate<number>('user_id',user.id??1)AppStorage.setOrCreate<string>('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 组件生命周期是管理数据、动画和资源的核心工具。本文通过项目中的实际代码案例,总结了各生命周期方法的调用时机和使用场景:

  1. aboutToAppear:组件初始化——加载数据、触发动画、启动定时器
  2. aboutToDisappear:资源清理——清除定时器、释放相机、关闭文件句柄
  3. onPageShow:页面刷新——每次显示时重新加载数据
  4. onPageHide:页面离开——暂停动画或资源消耗操作
  5. onReady:Canvas 就绪——首次绘制

核心原则:成对出现——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 官方示例
http://www.cnnetsun.cn/news/3261160.html

相关文章:

  • 如何构建企业级Python DDD架构:5个领域驱动设计实战策略
  • 71岁扩张型心肌病合并重度二尖瓣反流:合肥高新心血管病医院经导管二尖瓣夹合术突破高龄手术禁区
  • SPT-AKI存档编辑器终极指南:如何快速管理塔科夫离线版游戏进度
  • 香港公司注册地变更一般会选择哪些服务机构?
  • Cocos Creator Android打包:NDK版本选择与配置全攻略
  • PWM 控制 12V 直流电机实战:Arduino UNO R3 实现 0-300 转/分钟调速(附代码)
  • 154.工业级 PLC 编程范式|扫描周期避坑 + 时序防错 + 模块化 POU 设计
  • VR-Reversal完全指南:将3D VR视频转换为2D平面视频的终极解决方案
  • openEuler热补丁调试指南:使用debuginfo包进行热补丁故障排查的3种方法
  • 从牛津教材看成都高新区柏明顿等机构的RWI教学实施路径
  • TFT-LCD 接口技术对比:16位并行、SPI、RGB与MIPI DSI 的4种方案选型指南
  • 电梯曳引系统设计:3.3节受力计算与电机选型,功率误差控制在5%内
  • claude-real-video:智能视频关键帧提取与大模型高效理解方案
  • FastAPI+Docker部署AI聊天应用的生产实践
  • DVRP 两阶段算法实战:K-d树分割与混合搜索,36个算例求解效率分析
  • MLOps生产交付实战:从Notebook到高可用ML服务
  • 免费突破百度网盘限速:5分钟掌握Python解析工具终极指南
  • 基于协议化思想构建企业级AI Agent:动态集成与安全实践
  • RM-1000无线电综合测试仪:一体化检测设备在风电通信运维中的应用
  • GLM-5.2从POC到生产上线:KV Cache、max-num-seqs与验收清单
  • 世界杯催生“日酒夜咖”新节律:淘宝闪购上“啤酒+早餐”增长79.4%
  • 终极Windows右键菜单优化指南:ContextMenuManager让你的右键操作快如闪电
  • 大模型学习路线图:小白也能轻松入门,附全套学习资源(收藏必备)
  • 从零构建AI大模型应用平台:架构设计、核心模块与工程实践
  • 杭州吟颂调研:职称评审不通过原因深度解析——那些评委不会明说的“潜规则”
  • ESP8266 NodeMCU 引脚避坑指南:避开5个启动陷阱与3个功能限制
  • Verilog 按键消抖 3 种方案对比:状态机 vs 计数器 vs 边沿检测(附 50MHz 时钟实测)
  • x86 CPU Cache层级与容量实测:C++代码探测L1/L2/L3大小与Cache Line
  • 2026架构前沿:将Declarative Crawler(声明式爬虫)引入你的技术栈
  • Ubuntu 18.04深度学习GPU驱动安装:NVIDIA.run手动部署全指南