HarmonyOS 6.0 AbilityStage与多HAP初始化——大型应用拆模块的正确打开方式
一个应用只有一个 entry HAP 还好说,一旦拆成 entry + 多个 feature HAP,每个模块怎么初始化?数据库在哪个时机打开?资源预加载在哪里做?答案就是 AbilityStage——HAP 级别的"Application",每个 HAP 加载时第一个触发的生命周期。这篇把 AbilityStage 的所有回调和多 HAP 管理讲清楚。
AbilityStage 是什么
如果把 UIAbility 比作 Activity,那 AbilityStage 就是每个 HAP 的 Application:
| 对比 | Application | AbilityStage |
|---|---|---|
| 作用域 | 整个应用 | 单个 HAP |
| 触发时机 | 应用启动 | HAP 首次加载 |
| 数量 | 1 个 | 每个 HAP 1 个 |
| 主要用途 | 全局初始化 | 模块级初始化 |
import { AbilityStage, AbilityConstant, Want, Configuration } from '@kit.AbilityKit'

创建 AbilityStage
1. 实现 AbilityStage 类
// entry/src/main/ets/myabilitystage/MyAbilityStage.ets
export default class MyAbilityStage extends AbilityStage {
onCreate(): void {
console.info('MyAbilityStage onCreate')
// 模块级初始化:数据库、网络、资源预加载
this.initModuleResources()
}
onAcceptWant(want: Want): string {
// specified 模式下返回实例标识
if (want.action === 'action.share') {
return 'share_instance_' + want.parameters?.deviceId
}
return ''
}
onConfigurationUpdate(newConfig: Configuration): void {
console.info('onConfigurationUpdate: ' + JSON.stringify(newConfig))
// 语言/深浅色变更时更新模块资源
}
onMemoryLevel(level: AbilityConstant.MemoryLevel): void {
console.info('onMemoryLevel: ' + level)
// 根据内存级别释放非必要资源
if (level === AbilityConstant.MemoryLevel.MEMORY_LEVEL_CRITICAL) {
this.releaseCache()
}
}
private initModuleResources(): void {
// 初始化数据库连接
// 预加载配置数据
// 注册模块事件监听
}
private releaseCache(): void {
// 释放图片缓存
// 清理临时数据
}
}
2. 在 module.json5 中注册
{
"module": {
"name": "entry",
"type": "entry",
"srcEntry": "./ets/myabilitystage/MyAbilityStage.ets",
"abilities": [
{
"name": "EntryAbility",
"srcEntry": "./ets/entryability/EntryAbility.ets"
}
]
}
}
要点: srcEntry 指定 AbilityStage 脚本路径。HAP 首次加载时,系统先创建 AbilityStage(触发 onCreate),再创建 UIAbility。
四大回调详解
onCreate——模块初始化
HAP 加载时触发,是最早的初始化时机。
onCreate(): void {
// 适合做的事:
// 1. 初始化模块数据库
// 2. 预加载配置数据
// 3. 注册全局事件监听
// 4. 初始化网络SDK
// 不适合做的事:
// 1. 耗时操作(会阻塞 HAP 加载)
// 2. UI 操作(此时还没 UI)
// 3. 路由跳转(Ability 还没创建)
}
要点: onCreate 只在 HAP 首次加载时触发一次,不会重复触发。如果 HAP 已经加载过,后续启动 Ability 不会再触发 onCreate。
onAcceptWant——specified 模式实例标识
当 UIAbility 的 launchType 为 specified 时,系统通过 onAcceptWant 返回的字符串决定复用还是新建实例。
onAcceptWant(want: Want): string {
// 返回空字符串 → 每次新建实例
// 返回相同字符串 → 复用已有实例
if (want.action === 'action.document.edit') {
let docId: string = want.parameters?.docId as string
return 'doc_' + docId // 同一文档复用同一实例
}
if (want.action === 'action.contact.detail') {
let contactId: string = want.parameters?.contactId as string
return 'contact_' + contactId
}
return ''
}
要点: onAcceptWant 只对 specified 启动模式生效。返回的字符串就是实例的"身份证",相同身份证复用实例,不同身份证新建实例。
onConfigurationUpdate——配置变更
系统语言、深浅色、字体大小等配置变更时触发。
onConfigurationUpdate(newConfig: Configuration): void {
if (newConfig.language !== undefined) {
// 语言变更,重新加载多语言资源
this.reloadI18nResources(newConfig.language)
}
if (newConfig.colorMode !== undefined) {
// 深浅色切换
if (newConfig.colorMode === ConfigurationConstant.ColorMode.COLOR_MODE_DARK) {
this.applyDarkTheme()
} else {
this.applyLightTheme()
}
}
}
要点: Configuration 包含 language、colorMode、fontSize 等字段。不是每个字段每次都会变,检查 undefined 判断哪个配置变了。
onMemoryLevel——内存告警
系统内存紧张时触发,按级别释放资源。
onMemoryLevel(level: AbilityConstant.MemoryLevel): void {
// MEMORY_LEVEL_MODERATE = 0 → 适度释放
// MEMORY_LEVEL_LOW = 1 → 释放较多缓存
// MEMORY_LEVEL_CRITICAL = 2 → 释放所有非必要资源
if (level >= AbilityConstant.MemoryLevel.MEMORY_LEVEL_LOW) {
// 清理图片缓存
// 释放临时数据
// 关闭非活跃连接
}
if (level === AbilityConstant.MemoryLevel.MEMORY_LEVEL_CRITICAL) {
// 释放所有可释放资源
// 保存关键数据
// 准备被系统回收
}
}
要点: 内存级别从 MODERATE → LOW → CRITICAL 递增。收到 CRITICAL 时要立即释放资源,否则系统可能直接杀进程。
多 HAP 场景:每个模块独立初始化
大型应用拆成多个 HAP 后,每个 HAP 有自己的 AbilityStage:
MyApp/
├── entry/ → EntryAbilityStage (全局数据库、账号)
│ └── srcEntry: ./ets/EntryAbilityStage.ets
├── share/ → ShareAbilityStage (分享SDK初始化)
│ └── srcEntry: ./ets/ShareAbilityStage.ets
└── payment/ → PaymentAbilityStage (支付SDK初始化)
└── srcEntry: ./ets/PaymentAbilityStage.ets
// entry 模块的 AbilityStage
export default class EntryAbilityStage extends AbilityStage {
onCreate(): void {
// 初始化全局数据库
// 检查登录态
// 预加载首页数据
}
}
// share 模块的 AbilityStage
export default class ShareAbilityStage extends AbilityStage {
onCreate(): void {
// 初始化分享SDK
// 注册分享平台
}
}
// payment 模块的 AbilityStage
export default class PaymentAbilityStage extends AbilityStage {
onCreate(): void {
// 初始化支付SDK
// 加载商品配置
}
}
要点: feature HAP 的 AbilityStage 在该 HAP 首次被访问时才触发 onCreate,实现了按需初始化——不用就不加载,省内存省启动时间。
specified 启动模式与 onAcceptWant 配合
三种启动模式对比:
| 启动模式 | 实例数量 | onAcceptWant | 适用场景 |
|---|---|---|---|
| singleton | 1 个 | 不触发 | 全局唯一(主页、设置) |
| multiton | 多个 | 不触发 | 每次启动新建(已废弃) |
| specified | 按需 | 触发 | 同标识复用(文档编辑) |
// module.json5
{
"abilities": [
{
"name": "DocumentAbility",
"launchType": "specified"
}
]
}
// AbilityStage.onAcceptWant
onAcceptWant(want: Want): string {
// 打开文档A → 返回 'doc_A' → 复用已有 doc_A 实例
// 打开文档B → 返回 'doc_B' → 没有 doc_B 实例,新建
let docId: string = want.parameters?.docId as string
return 'doc_' + docId
}
完整 Demo 代码
Demo 模拟了 AbilityStage 生命周期回调和多 HAP 模块加载过程。
interface StageEvent {
name: string;
time: string;
detail: string;
}
interface ModuleInfo {
name: string;
type: string;
stageReady: boolean;
abilities: string[];
}
@Entry
@Component
struct AbilityStageDemo {
@State stageLog: StageEvent[] = [];
@State moduleList: ModuleInfo[] = [];
@State currentPhase: string = '';
@State memoryLevel: string = '正常';
aboutToAppear(): void {
this.moduleList = [
{ name: 'entry', type: 'entry', stageReady: true, abilities: ['EntryAbility'] },
{ name: 'share', type: 'feature', stageReady: false, abilities: ['ShareAbility'] },
{ name: 'payment', type: 'feature', stageReady: false, abilities: ['PayAbility'] }
];
}
build() {
Column({ space: 0 }) {
Row() {
Button('< 返回')
.fontSize(14)
.backgroundColor(Color.Transparent)
.fontColor('#1a73e8')
.onClick(() => { router.back(); })
Text('AbilityStage 初始化')
.fontSize(18)
.fontWeight(FontWeight.Bold)
.layoutWeight(1)
.textAlign(TextAlign.Center)
Text(this.memoryLevel)
.fontSize(12)
.fontColor(this.memoryLevel === '正常' ? '#4CAF50' : '#F44336')
}
.width('100%')
.height(56)
.padding({ left: 12, right: 12 })
.alignItems(VerticalAlign.Center)
.backgroundColor('#FFFFFF')
Scroll() {
Column({ space: 16 }) {
Column({ space: 12 }) {
Text('AbilityStage 生命周期')
.fontSize(16)
.fontWeight(FontWeight.Bold)
.width('100%')
Row({ space: 8 }) {
Button('onCreate').onClick(() => this.simulateEvent('onCreate', 'HAP加载,初始化资源'))
Button('onAcceptWant').onClick(() => this.simulateEvent('onAcceptWant', 'specified模式返回Key'))
Button('onConfigUpdate').onClick(() => this.simulateEvent('onConfigurationUpdate', '语言/深浅色变更'))
Button('onMemoryLevel').onClick(() => this.simulateEvent('onMemoryLevel', '系统内存告警'))
}
}
.width('100%')
.padding(16)
.borderRadius(12)
.backgroundColor('#FFFFFF')
Column({ space: 12 }) {
Text('多HAP模块管理')
.fontSize(16)
.fontWeight(FontWeight.Bold)
.width('100%')
ForEach(this.moduleList, (mod: ModuleInfo) => {
Row({ space: 12 }) {
Column()
.width(8)
.height(8)
.borderRadius(4)
.backgroundColor(mod.stageReady ? '#4CAF50' : '#E0E0E0')
Column({ space: 2 }) {
Text(mod.name).fontSize(15).fontWeight(FontWeight.Medium)
Text(`类型: ${mod.type} | Ability: ${mod.abilities.join(', ')}`)
.fontSize(12).fontColor('#999999')
}
.layoutWeight(1)
.alignItems(HorizontalAlign.Start)
Text(mod.stageReady ? '已加载' : '未加载')
.fontSize(12)
.fontColor(mod.stageReady ? '#4CAF50' : '#999999')
Button('加载')
.fontSize(12).height(28).enabled(!mod.stageReady)
.onClick(() => {
mod.stageReady = true;
this.simulateEvent('onCreate', `${mod.name}模块加载`);
})
}
.width('100%')
.padding(12)
.borderRadius(8)
.backgroundColor('#FAFAFA')
}, (mod: ModuleInfo) => mod.name)
}
.width('100%')
.padding(16)
.borderRadius(12)
.backgroundColor('#FFFFFF')
if (this.stageLog.length > 0) {
Column({ space: 8 }) {
Row() {
Text(`生命周期日志 (${this.stageLog.length})`)
.fontSize(16).fontWeight(FontWeight.Bold).layoutWeight(1)
Button('清除').fontSize(12).height(28)
.onClick(() => { this.stageLog = []; })
}
ForEach(this.stageLog.slice().reverse(), (event: StageEvent) => {
Row({ space: 8 }) {
Text(event.time).fontSize(11).fontColor('#999999').width(60)
Text(event.name).fontSize(13).fontWeight(FontWeight.Medium)
.fontColor(this.getEventColor(event.name)).width(110)
Text(event.detail).fontSize(12).fontColor('#666666').layoutWeight(1)
}
.width('100%').padding(4)
}, (event: StageEvent, index: number) => `${index}`)
}
.width('100%')
.padding(16)
.borderRadius(12)
.backgroundColor('#FFFFFF')
}
}
.padding(16)
}
.layoutWeight(1)
.width('100%')
}
.width('100%')
.height('100%')
.backgroundColor('#F5F5F5')
}
private simulateEvent(name: string, detail: string): void {
this.currentPhase = name
this.stageLog.push({
name: name,
time: new Date().toLocaleTimeString(),
detail: detail
})
if (name === 'onMemoryLevel') {
this.memoryLevel = '内存紧张'
setTimeout(() => { this.memoryLevel = '正常'; }, 3000)
}
}
private getEventColor(name: string): string {
if (name === 'onCreate') return '#1565C0'
if (name === 'onAcceptWant') return '#2E7D32'
if (name === 'onConfigurationUpdate') return '#E65100'
if (name === 'onMemoryLevel') return '#C62828'
return '#333333'
}
}
Application vs AbilityStage 初始化分工
| 初始化内容 | 放 Application | 放 AbilityStage |
|---|---|---|
| 全局数据库 | ✓ | |
| 账号/登录态 | ✓ | |
| 模块数据库 | ✓ | |
| SDK 初始化 | ✓(按模块) | |
| 资源预加载 | ✓(按需) | |
| 网络全局配置 | ✓ | |
| 模块路由表 | ✓ |
要点: 全局共享的放 Application,模块独有的放 AbilityStage。避免在 Application 里做所有初始化——feature HAP 没加载就白初始化了。
踩坑清单
| 问题 | 原因 | 解决 |
|---|---|---|
| onCreate 不触发 | module.json5 未配置 srcEntry | 添加 srcEntry 字段 |
| onAcceptWant 不触发 | UIAbility launchType 不是 specified | 改为 specified 模式 |
| specified 模式每次都新建 | onAcceptWant 返回空字符串 | 返回唯一标识字符串 |
| 配置变更不回调 | 未实现 onConfigurationUpdate | 实现 onConfigurationUpdate |
| 内存告警不回调 | 系统内存还够 | 模拟器上难触发,真机低内存测试 |
| HAP 加载慢 | onCreate 里做耗时操作 | 耗时操作放 Worker 或延迟执行 |
| 多 HAP 共享数据库冲突 | 两个 HAP 同时初始化 | 放到 Application 全局初始化一次 |
| AbilityStage 引用不到 context | onCreate 里 this.context 可能为空 | 用 UIAbility 的 context 替代 |
| feature HAP onCreate 时机不确定 | 按需加载 | 首次打开该模块 Ability 时触发 |
| onCreate 和 Ability.onCreate 顺序 | Stage 先于 Ability | 依赖 Ability 的逻辑不要放 Stage |
更多推荐

所有评论(0)