UIAbility 生命周期在日记 App 中的实践

前言

欢迎阅读《HarmonyOS 应用开发实战》系列文章。本系列基于开源项目 "海风日记"(一款 HarmonyOS 原生日记 App)的完整源码,深入剖析 ArkUI 组件、Kit 能力与鸿蒙特性在真实项目中的落地实践。

UIAbility 是 HarmonyOS Stage 模型下应用能力的核心入口,理解其生命周期是开发鸿蒙应用的第一步。本文将结合"海风日记"的 EntryAbility.ets 源码,详细讲解 UIAbility 的各个生命周期回调、窗口管理以及实际开发中的最佳实践。


一、UIAbility 概述

1.1 什么是 UIAbility

UIAbility 是 HarmonyOS Stage 模型中应用能力的抽象基类 ,它替代了 FA 模型中的 Ability,提供了更清晰的生命周期管理和窗口管理能力。每个 UIAbility 对应一个独立的应用窗口,可以理解为用户可见的一个"页面容器"。

1.2 Stage 模型 vs FA 模型

在 HarmonyOS 的发展历程中,Stage 模型是推荐的应用开发模型,相比旧的 FA 模型,它有以下优势:

特性 FA 模型 Stage 模型
生命周期 分散在多个回调 统一在 UIAbility 中管理
窗口管理 通过 Context 间接操作 通过 WindowStage 直接管理
组件化 能力较弱 支持多 HAP 和 HSP 共享包
后台任务 支持有限 提供 WorkScheduler 等标准 API
推荐程度 兼容保留 官方推荐

1.3 UIAbility 的核心职责

UIAbility 承担了以下关键职责:

  1. 生命周期管理:管理应用的创建、启动、前后台切换、销毁
  2. 窗口管理:创建和管理应用窗口,包括状态栏、导航栏等
  3. 页面加载:通过 WindowStage 加载首屏页面
  4. Ability 间通信:支持 Want 隐式/显式启动
  5. 配置管理:读取 module.json5 中的模块配置

提示 :每个 Entry 类型的 HAP 模块只能有一个 EntryAbility,且必须在 module.json5 中配置 mainElement 字段。


二、海风日记的 EntryAbility 源码分析

2.1 完整源码

"海风日记"的入口能力定义在 entryability/EntryAbility.ets 中,代码如下:

typescript 复制代码
import { UIAbility, Want, AbilityConstant } from '@kit.AbilityKit'
import { window } from '@kit.ArkUI'
import { hilog } from '@kit.PerformanceAnalysisKit'

const TAG = 'EntryAbility'
const DOMAIN = 0xFF00

export default class EntryAbility extends UIAbility {
  onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
    hilog.info(DOMAIN, TAG, '海风日记 onCreate')
  }

  onDestroy(): void {
    hilog.info(DOMAIN, TAG, 'onDestroy')
  }

  onWindowStageCreate(windowStage: window.WindowStage): void {
    hilog.info(DOMAIN, TAG, 'onWindowStageCreate')

    windowStage.loadContent('pages/SplashPage', (err) => {
      if (err.code !== 0) {
        hilog.error(DOMAIN, TAG, `loadContent failed: ${JSON.stringify(err)}`)
        return
      }
      hilog.info(DOMAIN, TAG, 'loadContent success')
    })

    windowStage.getMainWindow().then((win) => {
      win.setWindowSystemBarProperties({
        statusBarColor: '#00000000',
        statusBarContentColor: '#2D2926'
      })
    })
  }

  onWindowStageDestroy(): void {}
  onForeground(): void {}
  onBackground(): void {}
}

2.2 代码结构分析

这段代码虽然简短,但包含了 UIAbility 的核心生命周期回调,我们可以将其拆解为以下几个部分:

回调方法 触发时机 典型用途
onCreate Ability 首次创建时 初始化数据、日志埋点
onDestroy Ability 销毁时 释放资源、保存状态
onWindowStageCreate 窗口阶段创建时 加载首屏页面、配置窗口
onWindowStageDestroy 窗口阶段销毁时 清理窗口相关资源
onForeground Ability 进入前台时 恢复 UI 状态
onBackground Ability 进入后台时 保存临时数据

三、生命周期详解

3.1 onCreate:Ability 的创建入口

onCreate 在 Ability 首次创建时被调用,是整个应用生命周期的起点。在"海风日记"中,我们在此处记录日志:

typescript 复制代码
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
  hilog.info(DOMAIN, TAG, '海风日记 onCreate')
}

onCreate 接收两个参数:

  • want:启动该 Ability 的请求信息,包含 bundleNameabilityNameuriparameters
  • launchParam:启动参数,包含 launchReason(启动原因)、lastExitReason(上次退出原因)等

提示onCreate 中不应执行耗时操作,否则会影响应用启动速度。建议将数据初始化依赖注入 等操作放在此处,而页面渲染 相关的操作放在 onWindowStageCreate 中。

3.2 onDestroy:Ability 的销毁清理

当 Ability 被销毁时,onDestroy 被调用。注意 :这不是用户关闭应用时一定触发的回调,系统可能会在后台直接杀死进程而不调用 onDestroy

typescript 复制代码
onDestroy(): void {
  hilog.info(DOMAIN, TAG, 'onDestroy')
}

onDestroy 适合做以下操作:

  1. 释放数据库连接
  2. 取消订阅的事件
  3. 停止后台任务
  4. 保存关键数据到持久化存储

3.3 onWindowStageCreate:窗口创建与首屏加载

这是最关键的生命周期回调。当 UIAbility 的窗口阶段创建完成后,系统会回调此方法,我们可以在此处加载首屏页面和配置窗口属性。

typescript 复制代码
onWindowStageCreate(windowStage: window.WindowStage): void {
  hilog.info(DOMAIN, TAG, 'onWindowStageCreate')

  // 第一步:加载首屏页面
  windowStage.loadContent('pages/SplashPage', (err) => {
    if (err.code !== 0) {
      hilog.error(DOMAIN, TAG, `loadContent failed: ${JSON.stringify(err)}`)
      return
    }
    hilog.info(DOMAIN, TAG, 'loadContent success')
  })

  // 第二步:配置窗口属性
  windowStage.getMainWindow().then((win) => {
    win.setWindowSystemBarProperties({
      statusBarColor: '#00000000',      // 透明状态栏
      statusBarContentColor: '#2D2926'  // 状态栏文字颜色
    })
  })
}

loadContent 方法用于加载指定路径的页面作为首屏。路径配置在 main_pages.json 中:

json 复制代码
{
  "src": [
    "pages/SplashPage",
    "pages/Index",
    "pages/onboarding/OnboardingPage"
  ]
}

3.4 onForeground 与 onBackground:前后台切换

当应用在前台和后台之间切换时,这两个回调被触发:

typescript 复制代码
onForeground(): void {
  // 应用进入前台:恢复 UI 更新、刷新数据
}

onBackground(): void {
  // 应用进入后台:暂停动画、保存草稿
}

这两个回调的实际应用场景:

  1. onForeground 适合做

    • 恢复动画播放
    • 刷新数据列表
    • 重新建立网络连接
  2. onBackground 适合做

    • 暂停动画和计时器
    • 自动保存日记草稿
    • 释放内存资源

四、窗口管理实战

4.1 获取 MainWindow 对象

windowStage.getMainWindow() 返回一个 Promise,用于获取当前主窗口的引用:

typescript 复制代码
windowStage.getMainWindow().then((win) => {
  // win 是 MainWindow 实例
})

4.2 设置状态栏样式

"海风日记"通过 setWindowSystemBarProperties 方法设置状态栏为透明,并指定状态栏内容颜色:

typescript 复制代码
win.setWindowSystemBarProperties({
  statusBarColor: '#00000000',      // 完全透明
  statusBarContentColor: '#2D2926'  // 暖棕黑文字
})

setWindowSystemBarProperties 支持的配置项:

属性 类型 说明
statusBarColor string 状态栏背景色,#00000000 为透明
statusBarContentColor string 状态栏内容颜色(时钟、电量等图标文字)
navigationBarColor string 导航栏背景色
navigationBarContentColor string 导航栏按钮颜色

4.3 窗口其他配置

除了状态栏,MainWindow 还提供了丰富的配置接口:

typescript 复制代码
// 设置窗口全屏
win.setWindowLayoutFullScreen(true)

// 设置窗口是否可调整大小
win.setWindowResizable(false)

// 设置窗口背景色
win.setWindowBackgroundColor('#FAFAF7')

// 获取窗口尺寸
win.getWindowProperties().windowRect

4.4 窗口管理的最佳实践

在实际开发中,窗口管理应遵循以下原则:

  1. 尽早配置 :在 onWindowStageCreate 中尽早完成窗口配置,避免页面加载后出现视觉闪烁
  2. 状态栏适配:根据页面主题动态调整状态栏颜色,深色页面使用浅色状态栏文字
  3. 安全区域 :使用 expandSafeArea 或 SafeArea 组件适配挖孔屏和圆角

五、日志系统集成

5.1 hilog 日志 API

"海风日记"使用 hilog(来自 @kit.PerformanceAnalysisKit)进行日志输出:

typescript 复制代码
import { hilog } from '@kit.PerformanceAnalysisKit'

const TAG = 'EntryAbility'
const DOMAIN = 0xFF00

hilog.info(DOMAIN, TAG, '海风日记 onCreate')

hilog 的日志级别:

级别 方法 说明
DEBUG hilog.debug 调试信息,仅在 DEBUG 版本输出
INFO hilog.info 一般信息,记录关键事件
WARN hilog.warn 警告信息,不影响功能的问题
ERROR hilog.error 错误信息,影响功能的问题
FATAL hilog.fatal 致命错误,会导致应用崩溃

5.2 DOMAIN 和 TAG 的作用

typescript 复制代码
const DOMAIN = 0xFF00  // 应用自定义域标识
const TAG = 'EntryAbility'  // 模块标签
  • DOMAIN :取值范围 0x0 ~ 0xFFFF,用于区分不同应用的日志
  • TAG:用于标识日志的来源模块,方便过滤

提示 :在大型项目中,建议为每个模块定义独立的 TAG,如 'HomeTab''DiaryDetail' 等,便于日志定位问题。

5.3 日志查看工具

查看 hilog 输出的命令:

bash 复制代码
# 查看所有日志
hilog

# 过滤特定 TAG
hilog | grep EntryAbility

# 过滤特定级别
hilog -t info

# 清除日志缓冲区
hilog -r

六、module.json5 配置详解

6.1 模块配置

UIAbility 的注册信息在 module.json5 中配置:

json5 复制代码
{
  "module": {
    "name": "entry",
    "type": "entry",
    "mainElement": "EntryAbility",
    "deviceTypes": ["phone"],
    "abilities": [
      {
        "name": "EntryAbility",
        "srcEntry": "./ets/entryability/EntryAbility.ets",
        "description": "$string:EntryAbility_desc",
        "icon": "$media:app_icon",
        "label": "$string:EntryAbility_label",
        "startWindowIcon": "$media:app_icon",
        "startWindowBackground": "$color:start_window_background",
        "exported": true,
        "skills": [
          {
            "entities": ["entity.system.home"],
            "actions": ["action.system.home"]
          }
        ]
      }
    ]
  }
}

6.2 关键配置项说明

配置项 说明 示例值
name Ability 名称,需与代码类名一致 "EntryAbility"
srcEntry 源码入口路径 "./ets/entryability/EntryAbility.ets"
startWindowIcon 启动窗口图标 "$media:app_icon"
startWindowBackground 启动窗口背景色 "$color:start_window_background"
exported 是否允许其他应用调用 true
skills 意图过滤器,声明能处理的 Intent 支持 home 入口

6.3 启动窗口配置

startWindowIconstartWindowBackground 用于配置冷启动时的启动窗口(Splash Window),在应用的首帧渲染完毕前显示。这是一个重要的用户体验优化点:

  • 建议将 startWindowBackground 设置为应用的主题色或品牌色
  • 避免使用纯白色作为启动背景,减少视觉突兀感

七、UIAbility 的完整生命周期时序图

UIAbility 的完整生命周期流转如下:

复制代码
用户启动应用
     ↓
onCreate()          ← 首次创建
     ↓
onWindowStageCreate()  ← 窗口创建
     ↓
onForeground()      ← 进入前台
     ↓
  [应用运行中]
     ↓
用户按 Home 键 / 切到后台
     ↓
onBackground()      ← 进入后台
     ↓
用户回到应用
     ↓
onForeground()      ← 回到前台
     ↓
用户关闭应用
     ↓
onWindowStageDestroy()  ← 窗口销毁
     ↓
onDestroy()         ← Ability 销毁

7.1 异常场景处理

在实际开发中,还需要考虑以下异常场景:

  1. 进程被系统杀死onDestroy 可能不会被调用,需要依赖 onBackground 保存关键数据
  2. 配置变更 (如屏幕旋转):默认会销毁并重建 Ability,可通过 configChanges 配置避免
  3. 多实例启动 :通过 launchTypesingleton / standard / multiton)控制实例模式

7.2 各回调的触发次数

回调 触发次数 说明
onCreate 整个生命周期1次 除非进程被杀死后重新启动
onForeground 多次 每次回到前台触发
onBackground 多次 每次进入后台触发
onDestroy 整个生命周期1次 正常销毁时触发

八、常见问题与排查

8.1 loadContent 失败

如果 loadContent 返回错误码,可能的原因:

  • 路径错误 :检查 main_pages.json 中是否注册了该页面路径
  • 页面组件未使用 @Entry 装饰 :每个页面必须使用 @Entry 装饰
  • 资源引用错误:检查页面中引用的字符串、颜色等资源是否存在
typescript 复制代码
// 错误处理示例
windowStage.loadContent('pages/SplashPage', (err) => {
  if (err.code !== 0) {
    // 记录详细错误信息
    hilog.error(DOMAIN, TAG, `loadContent failed: ${JSON.stringify(err)}`)
    return
  }
})

8.2 状态栏颜色不生效

检查以下几项:

  1. 是否在 onWindowStageCreate尽早调用
  2. statusBarColor 是否使用 8 位色值(含 Alpha 通道)
  3. statusBarContentColor 是否使用 6 位色值(不含 Alpha)
typescript 复制代码
// 正确的配置方式
win.setWindowSystemBarProperties({
  statusBarColor: '#00000000',       // 8 位,含 Alpha
  statusBarContentColor: '#2D2926'   // 6 位,不含 Alpha
})

8.3 应用启动白屏

应用启动时出现短暂白屏,通常是因为启动窗口配置不当:

json5 复制代码
{
  "startWindowIcon": "$media:app_icon",
  "startWindowBackground": "$color:start_window_background"
}

建议将 startWindowBackground 设置为应用的品牌主色页面背景色,与首屏页面颜色保持一致,减少视觉跳跃。


总结

本文从"海风日记"的 EntryAbility.ets 源码出发,深入剖析了 UIAbility 的完整生命周期和窗口管理机制。核心要点如下:

  1. UIAbility 是 Stage 模型的核心入口,管理着应用的生命周期和窗口
  2. onCreate → onWindowStageCreate → onForeground 是启动时的标准流程
  3. onWindowStageCreate 是最重要的回调,负责加载首屏和配置窗口
  4. hilog 日志系统为应用调试提供了有力支持
  5. module.json5 中的配置直接影响 Ability 的行为

下一篇文章将深入讲解 WindowStage 窗口管理,包括透明状态栏的实现、沉浸式布局的适配以及安全区域的处理,敬请期待。

如果这篇文章对你有帮助,欢迎点赞👍、收藏⭐、关注🔔,你的支持是我持续创作的动力!


相关资源:

相关推荐
tyqtyq2213 小时前
旅行打包清单 App — HarmonyOS AI 应用开发技术博客
人工智能·学习·华为·生活·harmonyos
HONG````13 小时前
Lazy Import 动态加载:减少 HarmonyOS 应用冷启动时间
harmonyos
大阳光男孩14 小时前
Spring Boot 整合 Debezium 实现 MySQL 增量数据监听(嵌入式版)
spring boot·后端·mysql
皮皮林55114 小时前
ThreadLocal 不香了?ScopedValue才是王道?
后端
X-⃢_⃢-X15 小时前
一、第一阶段:认识 Spring Boot
java·spring boot·后端
前端工作日常15 小时前
我学习到的Java程序的生命周期
java·后端
AskHarries17 小时前
GitHub 登录配置流程
后端
条tiao条17 小时前
Navigation页面跳转教学博客
ui·华为·harmonyos·鸿蒙·页面跳转
ZZZMMM.zip18 小时前
竞品分析框架-基于鸿蒙的AI竞品分析应用开发实践
人工智能·华为·harmonyos·鸿蒙系统