HarmonyOS应用开发实战:猫猫大作战-如何管理启动参数、初始化全局状态和预加载配置


前言
在 HarmonyOS 应用开发中,每个应用都有一个或多个 Ability 作为入口。其中 UIAbility 是包含 UI 界面的应用组件,负责管理应用窗口、生命周期和页面路由——它是整个应用的"大门"。
本文以「猫猫大作战」的 EntryAbility.ets 源码为主线,拆解 UIAbility 的完整生命周期、在 module.json5 中的注册方式,以及 onWindowStageCreate → loadContent 的首屏加载链路,带你吃透 HarmonyOS 应用入口的核心机制。
提示:本系列不讲 ArkTS 基础语法与环境搭建,假设你已跟完第 1–70 篇。本篇是阶段三第 71 篇。
一、项目中的 EntryAbility
1.1 源码定位
打开「猫猫大作战」项目 entry/src/main/ets/entryability/EntryAbility.ets,可以看到最精简的入口实现:
import { UIAbility, Want, AbilityConstant } from '@kit.AbilityKit';
import { window } from '@kit.ArkUI';
import { hilog } from '@kit.PerformanceAnalysisKit';
const TAG: string = 'EntryAbility';
const DOMAIN: number = 0xFF00;
export default class EntryAbility extends UIAbility {
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
hilog.info(DOMAIN, TAG, '%{public}s', 'Ability onCreate');
}
onDestroy() {
hilog.info(DOMAIN, TAG, '%{public}s', 'Ability onDestroy');
}
onWindowStageCreate(windowStage: window.WindowStage) {
hilog.info(DOMAIN, TAG, '%{public}s', 'Ability onWindowStageCreate');
windowStage.loadContent('pages/Index', (err) => {
if (err.code) {
hilog.error(DOMAIN, TAG, 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? '');
return;
}
hilog.info(DOMAIN, TAG, '%{public}s', 'Succeeded in loading the content.');
});
}
onWindowStageDestroy() {
hilog.info(DOMAIN, TAG, '%{public}s', 'Ability onWindowStageDestroy');
}
onForeground() {
hilog.info(DOMAIN, TAG, '%{public}s', 'Ability onForeground');
}
onBackground() {
hilog.info(DOMAIN, TAG, '%{public}s', 'Ability onBackground');
}
}
1.2 结构解析
| 元素 | 说明 | 来源 |
|---|---|---|
UIAbility |
基类,提供生命周期回调 | @kit.AbilityKit |
Want |
启动参数,携带目标、数据 | @kit.AbilityKit |
AbilityConstant |
启动原因常量 | @kit.AbilityKit |
WindowStage |
窗口阶段,承载 UI 加载 | @kit.ArkUI |
hilog |
系统日志工具 | @kit.PerformanceAnalysisKit |
二、UIAbility 生命周期全景
2.1 六个核心回调
UIAbility 的生命周期包含 6 个回调,调用顺序如下:
冷启动:onCreate → onWindowStageCreate → onForeground
↓
loadContent('pages/Index')
↓
Index 页面渲染(aboutToAppear → build → onDidBuild)
↓
切后台:onBackground
切前台:onNewWant → onForeground
↓
窗口销毁:onWindowStageWillDestroy → onWindowStageDestroy
应用退出:onDestroy
2.2 各回调用途速查
| 回调 | 触发时机 | 项目用途 |
|---|---|---|
onCreate |
首次创建 Ability 实例 | 初始化全局配置、日志 |
onWindowStageCreate |
WindowStage 创建完成后 | 加载首屏页面、订阅窗口事件 |
onForeground |
Ability 进入前台 | 恢复游戏/定位等资源 |
onBackground |
Ability 完全不可见 | 暂停游戏、释放资源 |
onWindowStageDestroy |
WindowStage 销毁后 | 释放 WindowStage 资源 |
onDestroy |
Ability 实例销毁前 | 保存数据、释放全局资源 |
2.3 各回调生命周期表
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 called');
// 此处可初始化全局数据,如 AppStorage 预置默认值
AppStorage.setOrCreate('highScore', 0);
}
onWindowStageCreate(windowStage: window.WindowStage): void {
// WindowStage 创建后加载首屏
hilog.info(DOMAIN, TAG, 'onWindowStageCreate called');
// 订阅 WindowStage 事件(获焦/失焦)
windowStage.on('windowStageEvent', (data) => {
const eventType: window.WindowStageEventType = data;
switch (eventType) {
case window.WindowStageEventType.ACTIVE:
hilog.info(DOMAIN, TAG, '窗口获焦');
break;
case window.WindowStageEventType.INACTIVE:
hilog.info(DOMAIN, TAG, '窗口失焦');
break;
case window.WindowStageEventType.HIDDEN:
hilog.info(DOMAIN, TAG, '窗口隐藏');
break;
default:
break;
}
});
// 加载首屏页面
windowStage.loadContent('pages/Index', (err) => {
if (err.code) {
hilog.error(DOMAIN, TAG, '加载页面失败: %{public}s', JSON.stringify(err));
return;
}
hilog.info(DOMAIN, TAG, '页面加载成功');
});
}
onForeground(): void {
hilog.info(DOMAIN, TAG, 'onForeground called');
// 回到前台:可恢复游戏引擎
}
onBackground(): void {
hilog.info(DOMAIN, TAG, 'onBackground called');
// 切到后台:可暂停游戏
}
onWindowStageDestroy(): void {
hilog.info(DOMAIN, TAG, 'onWindowStageDestroy called');
}
onDestroy(): void {
hilog.info(DOMAIN, TAG, 'onDestroy called');
// 保存高分到持久化存储
}
}
三、module.json5 中的注册
3.1 配置结构
UIAbility 必须在 module.json5 中注册才能被系统识别。猫猫大作战的 entry/src/main/module.json5:
{
"module": {
"name": "entry",
"type": "entry",
"deviceTypes": ["tablet", "phone", "wearable"],
"deliveryWithInstall": true,
"installationFree": false,
"pages": "$profile:main_pages",
"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": [
{
"actions": ["action.system.home"]
}
]
}
]
}
}
3.2 关键字段说明
| 字段 | 值 | 含义 |
|---|---|---|
name |
EntryAbility | Ability 名称,唯一标识 |
srcEntry |
./ets/entryability/EntryAbility.ets |
源码路径 |
exported |
true |
允许其他应用通过 Want 启动 |
skills[0].actions |
action.system.home |
桌面图标入口 |
startWindowIcon |
$media:app_icon |
启动窗口图标 |
startWindowBackground |
$color:start_window_background |
启动窗口背景色 |
注意:
srcEntry路径相对于entry/src/main/目录。exported为true时,其他应用可通过startAbility启动你的 Ability。
四、启动流程时序
4.1 冷启动时序
用户点击桌面图标
↓
Launcher 构造 Want → action.system.home
↓
AAFWK(Ability Manager Service)创建 UIAbility 实例
↓
onCreate(want, launchParam) ← ① 第一次初始化
↓
onWindowStageCreate(windowStage) ← ② 窗口创建
↓
windowStage.loadContent('pages/Index') ← ③ 加载页面
↓
Index.ets aboutToAppear → build → onDidBuild ← ④ 页面渲染
↓
onForeground() ← ⑤ 进入前台
↓
用户可见、可交互
4.2 热启动(从后台回到前台)
用户从最近任务/桌面重新打开
↓
onNewWant(want, launchParam) ← ① 携带新参数
↓
onForeground() ← ② 进入前台
↓
onPageShow() ← ③ Index 页面级回调
五、Want 与启动参数
5.1 Want 结构
onCreate 中接收的 Want 参数包含了启动的完整信息:
// Want 的核心字段
interface Want {
deviceId?: string; // 目标设备 ID(跨设备时使用)
bundleName?: string; // 目标应用 Bundle 名称
abilityName?: string; // 目标 Ability 名称
uri?: string; // 通用资源标识符
type?: string; // MIME 类型
parameters?: Record<string, Object>; // 自定义参数
flags?: number; // 启动标记
}
5.2 在 EntryAbility 中解析启动参数
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
// 解析启动原因
switch (launchParam.launchReason) {
case AbilityConstant.LaunchReason.START_ABILITY:
hilog.info(DOMAIN, TAG, '通过 startAbility 启动');
break;
case AbilityConstant.LaunchReason.CALL:
hilog.info(DOMAIN, TAG, '通过 call 启动');
break;
case AbilityConstant.LaunchReason.CONTINUATION:
hilog.info(DOMAIN, TAG, '通过跨端迁移启动');
break;
case AbilityConstant.LaunchReason.APP_RECOVERY:
hilog.info(DOMAIN, TAG, '通过应用恢复启动');
break;
default:
break;
}
// 解析自定义参数(比如通过 DeepLink 启动)
const targetPage = want.parameters?.['targetPage'] as string;
if (targetPage) {
AppStorage.setOrCreate('targetPage', targetPage);
}
}
六、常见踩坑
6.1 坑一:loadContent 路径错误
// 🚫 错误:路径多了 src/
windowStage.loadContent('src/main/ets/pages/Index', ...);
// ✅ 正确:路径相对于 entry/src/main/ets/
windowStage.loadContent('pages/Index', (err) => {
if (err.code) {
hilog.error(DOMAIN, TAG, '加载失败: %{public}s', JSON.stringify(err));
}
});
6.2 坑二:忘记在 module.json5 注册
// 🚫 错误:只写了文件,没在 abilities 数组中注册
{
"module": {
"abilities": [] // ❌ 空的,系统找不到 EntryAbility
}
}
表现:应用启动直接闪退,报 Cannot find ability。
6.3 坑三:onBackground 中做耗时操作
// 🚫 错误:onBackground 中执行数据库写入等耗时操作
onBackground(): void {
this.saveGameData(); // ❌ 可能耗时超过系统限制
}
// ✅ 正确:在 onPageHide 或异步任务中处理
onBackground(): void {
// 仅标记状态,不做耗时操作
AppStorage.set('isBackground', true);
}
onBackground()执行时间极短,不适合做数据库事务、网络请求等操作。
七、HiLog 日志验证
7.1 日志输出
在 DevEco Studio 中运行应用并过滤 EntryAbility,可以看到完整的生命周期调用链:
09:15:23.101 [INFO] EntryAbility: Ability onCreate
09:15:23.156 [INFO] EntryAbility: Ability onWindowStageCreate
09:15:23.201 [INFO] EntryAbility: Succeeded in loading the content.
09:15:23.225 [INFO] Index: Index aboutToAppear called
09:15:23.289 [INFO] Index: Index onDidBuild called
09:15:23.302 [INFO] EntryAbility: Ability onForeground
7.2 使用 hilog 替代 console
在 EntryAbility.ets 中,官方推荐使用 hilog 而非 console.log:
| 方面 | console | hilog |
|---|---|---|
| 性能 | 未优化 | 异步写入,不阻塞主线程 |
| 分级 | 无 | DEBUG/INFO/WARN/ERROR/FATAL |
| 过滤 | 按字符串 | 按 DOMAIN + TAG |
| 线上采集 | 不支持 | 支持 HiAppEvent 采集 |
// 推荐:在 EntryAbility 中使用 hilog
import { hilog } from '@kit.PerformanceAnalysisKit';
hilog.info(0xFF00, 'EntryAbility', '应用启动完成');
八、总结
EntryAbility 是 HarmonyOS 应用的起点,承载了冷启动初始化、窗口创建、首屏加载和前后台切换等核心职责。本文从「猫猫大作战」的实际源码出发,覆盖了 UIAbility 的六大生命周期回调、module.json5 注册规范、Want 参数解析和常见踩坑。
核心要点:
- UIAbility 生命周期:
onCreate→onWindowStageCreate→onForeground/onBackground→onDestroy loadContent('pages/Index')负责加载首屏页面module.json5中必须注册 Ability 才能被系统识别onBackground不允许做耗时操作- 用
hilog替代console.log进行日志输出
下一篇预告:第 72 篇将深入 onCreate 冷启动初始化,讲解如何管理启动参数、初始化全局状态和预加载配置。
如果这篇文章对你有帮助,欢迎点赞👍、收藏⭐、关注🔔,你的支持是我持续创作的动力!
相关资源:
更多推荐

所有评论(0)