Harmony os——UIAbility 组件生命周期|我按自己的理解梳了一遍

Harmony os------UIAbility 组件生命周期|我按自己的理解梳了一遍

这一篇是我在看官方文档时,自己消化后重写的版本,主要讲: UIAbility 在什么时候活过来、什么时候进前台 / 后台、什么时候被销毁,以及每个生命周期回调适合放什么逻辑。


1. 先搞清楚:UIAbility 的"几种状态"

从用户的角度看,一个 UIAbility 大概会经历这几种状态:

  • 被创建:第一次启动时
  • 进入前台:界面可见、可交互
  • 切到后台:界面不可见了
  • 被销毁:整个能力不再使用

从开发者的角度,对应的核心生命周期回调就是:

  • onCreate() -- 实例第一次创建
  • onWindowStageCreate() -- 窗口(WindowStage)准备好,装 UI 的时候
  • onForeground() -- 进入前台(UI 即将可见 / 可交互)
  • onBackground() -- 进入后台(UI 完全不可见)
  • onWindowStageWillDestroy() -- 窗口将被销毁(还能操作 WindowStage)
  • onWindowStageDestroy() -- 窗口已销毁(释放 UI 资源)
  • onDestroy() -- Ability 实例整个要结束
  • onNewWant() -- 已经存在的 UIAbility 再次被拉起时,用来"更新参数"的

一个很重要的点: 这些生命周期回调都是在"主线程"执行的,所以里面要尽量保持"轻量",耗时逻辑丢给子线程或异步。


2. 两种常见启动场景

官方文档里把 UIAbility 的生命周期拆成两个典型场景,我照着再说一遍:

2.1 场景一:正常启动到前台

这个是最常见的情况:用户点图标、点卡片、点通知,启动一个 UIAbility。

完整流程大概是:

  1. 首次启动时

    • onCreate()
    • onWindowStageCreate()
    • onForeground()
  2. 用户切到其他应用(当前 UIAbility 退到后台)

    • onBackground()
  3. 用户再切回来

    • onNewWant()(如果是再次通过 want 启动)
    • onForeground()

小记:

  • onCreate() 整个生命周期只跑 一次
  • 后续再进前台,不会再 onCreate(),只会触发 onNewWant() + onForeground()

2.2 场景二:通过 startAbilityByCall() 启动到后台

这个是比较"特别"的情况: 开发者通过 UIAbilityContext.startAbilityByCall() 把一个 UIAbility 启动在后台,一开始并不会显示 UI。

流程大概是:

  1. 启动到后台

    • onCreate()

    • onBackground()

    注意:这里 不会执行 onWindowStageCreate(),因为窗口还没建。

  2. 后面再把它拉到前台

    • onNewWant()
    • onWindowStageCreate()(此时才创建窗口并加载 UI)
    • onForeground()

这种模式适合那种:一开始先在后台准备数据,后面才需要 UI 界面的场景。


3. 每个生命周期回调适合做什么?

下面我按自己写代码时的习惯,把每个回调"怎么用"总结了一遍。


3.1 onCreate():只会执行一次的初始化

触发时机:

  • UIAbility 实例第一次创建的时候

适合做的事:

  • 整个生命周期只需要做一次的初始化:

    • 全局配置
    • 轻量的依赖初始化
    • 日志系统 / 埋点初始化(如果不放在 Application 里)
    • 初始化状态数据、单例注入等

示例:

scala 复制代码
 import { AbilityConstant, UIAbility, Want } from '@kit.AbilityKit';
 ​
 export default class EntryAbility extends UIAbility {
   onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
     // 只做"一次性"的初始化
     console.info('[EntryAbility] onCreate');
   }
 }

3.2 onWindowStageCreate():窗口准备好,加载 UI + 订阅窗口事件

触发时机:

  • UIAbility 实例创建之后
  • 进入前台之前
  • WindowStage 创建完成时

适合做的事:

  • 调用 windowStage.loadContent('pages/Index') 加载页面

  • 订阅窗口事件,比如:

    • 前台 / 后台(SHOWN / HIDDEN
    • 获焦 / 失焦(ACTIVE / INACTIVE
    • 可交互 / 不可交互(RESUMED / PAUSED

示例(精简版):

javascript 复制代码
 import { UIAbility } from '@kit.AbilityKit';
 import { window } from '@kit.ArkUI';
 ​
 export default class EntryAbility extends UIAbility {
   onWindowStageCreate(windowStage: window.WindowStage): void {
     // 订阅窗口事件
     windowStage.on('windowStageEvent', (event) => {
       switch (event) {
         case window.WindowStageEventType.SHOWN:
           console.info('WindowStage 前台');
           break;
         case window.WindowStageEventType.HIDDEN:
           console.info('WindowStage 后台');
           break;
         default:
           break;
       }
     });
 ​
     // 加载首页 UI
     windowStage.loadContent('pages/Index', () => {
       console.info('Index 页面加载完成');
     });
   }
 }

3.3 onForeground():进入前台,适合"重新占用资源"

触发时机:

  • UIAbility 即将进入前台、UI 即将可见 / 可交互之前

适合做的事:

  • 重新获取或启用前台才需要的资源:

    • 开启定位、传感器
    • 恢复相机预览
    • 重新注册某些前台监听

示例:

scala 复制代码
 export default class EntryAbility extends UIAbility {
   onForeground(): void {
     // 比如重新打开定位、相机、前台服务等
     console.info('[EntryAbility] onForeground');
   }
 }

3.4 onBackground():进入后台,释放不必要的前台资源

触发时机:

  • 当 UI 完全不可见后

适合做的事:

  • 停掉前台才需要的资源:

    • 停止定位
    • 关闭相机预览
    • 取消部分前台网络轮询
  • 不要做特别耗时的操作(比如大批量存盘、数据库大事务)

示例:

scala 复制代码
 export default class EntryAbility extends UIAbility {
   onBackground(): void {
     // 释放 UI 不可见时可以停掉的资源
     console.info('[EntryAbility] onBackground');
   }
 }

小提示:这个回调时间是很短的,更多是"关资源",不是"干重活"。


3.5 onWindowStageWillDestroy():窗口将销毁,还能操作 WindowStage

触发时机:

  • UIAbility 实例销毁之前
  • WindowStage 即将销毁,此时 WindowStage 仍然可用

适合做的事:

  • WindowStage 相关的收尾工作:

    • 取消事件订阅(windowStage.off('windowStageEvent')
    • 释放由 WindowStage 创建的相关资源

示例(重点是取消订阅):

typescript 复制代码
 import { UIAbility } from '@kit.AbilityKit';
 import { window } from '@kit.ArkUI';
 ​
 export default class EntryAbility extends UIAbility {
   private windowStage?: window.WindowStage;
 ​
   onWindowStageCreate(windowStage: window.WindowStage): void {
     this.windowStage = windowStage;
     // 订阅事件...
   }
 ​
   onWindowStageWillDestroy(windowStage: window.WindowStage): void {
     if (this.windowStage) {
       this.windowStage.off('windowStageEvent');
     }
     console.info('[EntryAbility] onWindowStageWillDestroy');
   }
 }

3.6 onWindowStageDestroy():窗口已经销毁,用来收尾 UI 资源

触发时机:

  • UIAbility 实例销毁前
  • WindowStage 已经销毁,不能再用它访问窗口

适合做的事:

  • 释放 UI 相关资源:

    • 清空某些 UI 层面的缓存
    • 重置 UI 状态(如果有必要)

示例:

scala 复制代码
 export default class EntryAbility extends UIAbility {
   onWindowStageDestroy(): void {
     // UI 资源收尾
     console.info('[EntryAbility] onWindowStageDestroy');
   }
 }

3.7 onDestroy():真正的"临终回调"

触发时机:

  • UIAbility 实例要被销毁前的最后一个生命周期回调

比如:

  • 你调用 terminateSelf() 主动结束当前 UIAbility 时;
  • 某些场景下系统清理时(注意:并不是所有清理都会走 onDestroy,见下面说明)。

适合做的事:

  • 释放系统资源、断开连接;
  • 持久化业务数据(注意不要太慢);
  • 做一些"善后"的日志记录。

注意几点:

  • 从 API 13 开始:

    • 无实况窗 的应用:用户在最近任务中"一键清理"时,进程可能直接被杀死,不触发 onDestroy()
    • 有实况窗的应用:仍然会走 onDestroy()
  • 调试时,从最近任务里划掉调试应用的某个任务,也可能直接杀进程,不走 onDestroy()

示例:

scala 复制代码
 export default class EntryAbility extends UIAbility {
   onDestroy(): void {
     // 释放资源、保存数据等
     console.info('[EntryAbility] onDestroy');
   }
 }

3.8 onNewWant():已存在实例再次被启动时

触发时机:

  • UIAbility 实例已经存在,再次调用启动它时 (比如单实例模式下,从其他地方再次 startAbility 这个 UIAbility)

适合做的事:

  • 根据新的 Want 更新页面要展示的内容:

    • 比如:从通知栏点进来,要跳到某个聊天窗口 / 详情页;
    • 或者:根据新的参数刷新数据。

示例:

scala 复制代码
 import { AbilityConstant, UIAbility, Want } from '@kit.AbilityKit';
 ​
 export default class EntryAbility extends UIAbility {
   onNewWant(want: Want, launchParam: AbilityConstant.LaunchParam): void {
     // 例如更新当前要展示的内容
     console.info('[EntryAbility] onNewWant, params: ' + JSON.stringify(want.parameters));
   }
 }

4. 如何"监听别的 UIAbility 的生命周期"?

有时候我们不只关心当前 Ability,还想从应用层面统一监听 UIAbility 生命周期变化,官方也提供了能力:

  • 可以通过 ApplicationContext 注册监听 UIAbility 生命周期事件。

这一块可以单独写一篇"如何用 ApplicationContext 监听 UIAbility 生命周期"的笔记,这里先留个坑。


5. 我自己的使用习惯小总结

我现在写 Stage 模型的 UIAbility,大概会按这个习惯来:

  • 一次性的初始化(全局级)onCreate()
  • UI 框架 & Window 设置onWindowStageCreate()
  • 开资源(定位、传感器、订阅前台事件等)onForeground()
  • 关资源(停止定位、停止前台轮询等)onBackground()
  • 取消窗口事件订阅 / Window 相关清理onWindowStageWillDestroy()
  • UI 资源收尾onWindowStageDestroy()
  • 业务级的"最后收尾"和数据持久化onDestroy()
  • 单实例重复启动时更新参数 / 跳转状态onNewWant()
相关推荐
汉堡黄2 小时前
鸿蒙开发:案例集合Tabs:自定义tabs突出(凸出)球体左右跟随滑动动画
harmonyos
Q***l6872 小时前
HarmonyOS在智能穿戴中的Huawei Watch
华为·harmonyos
p***43487 小时前
HarmonyOS系统架构
华为·系统架构·harmonyos
Y***K43410 小时前
HarmonyOS在智能穿戴中的健康算法
华为·harmonyos
1***815313 小时前
HarmonyOS在智能车载中的娱乐系统
华为·harmonyos·娱乐
4***R24013 小时前
HarmonyOS在智能车载中的车载娱乐
华为·harmonyos·娱乐
食品一少年14 小时前
【DAY1】零基础Flutter 编译开发 鸿蒙HarmonyOS
华为·harmonyos
T***160714 小时前
HarmonyOS在智能家居中的应用
华为·智能家居·harmonyos
马剑威(威哥爱编程)15 小时前
鸿蒙6开发中CANN Kit十大常见问题与解决方案
chrome·华为·harmonyos