一、Stage模型核心概念
1、设计理念
Stage模型通过进程隔离设计和组件生命周期解耦,实现了:
- 更好的性能与安全性:UI组件与后台任务分离
- 更清晰的应用架构:明确的应用组件边界
- 更便捷的数据共享:跨组件数据共享机制
2、核心概念
1) 应用组件
-
UIAbility:应用的入口和UI载体,代表一个独立的功能单元
-
ExtensionAbility:特定场景的扩展能力(如服务卡片、输入法)
-
WindowStage:UIAbility的窗口舞台,管理应用窗口
2)数据管理
-
AppStorage:应用级状态管理
-
Environment:环境状态管理
-
PersistentStorage:持久化存储
3)架构特点
javascript
┌────────────────────────────────┐
│ UIAbility组件 │
│ ┌─────────┐ ┌─────────────┐ │
│ │ 窗口 │ │ 上下文 │ │
│ │ Window │ │ Context │ │
│ └─────────┘ └─────────────┘ │
└────────────────────────────────┘
│ │
▼ ▼
┌─────────────────┐ ┌─────────────────┐
│ UI界面(ArkTS) │ 数据/状态管理 │
│ Pages/Components│ │ AppStorage等 │
└─────────────────┘ └─────────────────┘
二、UIAbility生命周期详解
UIAbility组件的核心生命周期回调包括onCreate、onForeground、onBackground、onDestroy。作为一种包含UI的应用组件,UIAbility的生命周期不可避免地与WindowStage的生命周期存在关联关系。
UI Ability生命周期示意图:

javascript
import { AbilityConstant, ConfigurationConstant, UIAbility, Want } from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { window } from '@kit.ArkUI';
const DOMAIN = 0x0000;
export default class EntryAbility extends UIAbility {
// 应用创建时调用
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
try {
this.context.getApplicationContext().setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_NOT_SET);
} catch (err) {
hilog.error(DOMAIN, 'testTag', 'Failed to set colorMode. Cause: %{public}s', JSON.stringify(err));
}
hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onCreate');
// 初始化应用资源
}
// 应用销毁
onDestroy(): void {
// 最终清理工作
hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onDestroy');
}
// 窗口舞台创建时调用
onWindowStageCreate(windowStage: window.WindowStage): void {
// Main window is created, set main page for this ability
hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageCreate');
// 设置UI加载内容
windowStage.loadContent('pages/Index', (err) => {
if (err.code) {
hilog.error(DOMAIN, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err));
return;
}
hilog.info(DOMAIN, 'testTag', 'Succeeded in loading the content.');
});
}
onWindowStageWillDestroy(windowStage: window.WindowStage): void {
hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageWillDestroy');
}
// 窗口舞台销毁
onWindowStageDestroy(): void {
// 清理窗口相关资源
// Main window is destroyed, release UI related resources
hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageDestroy');
}
// 应用从后台回到前台
onNewWant(want: Want, launchParam: AbilityConstant.LaunchParam): void {
hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onNewWant');
}
onWillForeground(): void {
hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWillForeground');
}
// 应用从后台回到前台
onForeground(): void {
// Ability has brought to foreground
hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onForeground');
}
onWillBackground(): void {
hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWillBackground');
}
// 应用从前台进入后台
onBackground(): void {
// Ability has back to background
hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onBackground');
}
}
1、运行程序查看对应的日志
当用户启动一个UIAbility时,系统会依次触发onCreate()、onWindowStageCreate()、onForeground()生命周期回调。
bash
Ability onCreate
Ability onWindowStageCreate
Ability onWillForeground
Ability onForeground
Succeeded in loading the content.
切到后台:
bash
Ability onWillBackground
Ability onBackground
切回前台:
bash
Ability onNewWant
Ability onWillForeground
Ability onForeground
杀掉app:
bash
Ability onWillBackground
Ability onBackground
Ability onWindowStageWillDestroy
Ability onWindowStageDestroy
Ability onDestroy
2、生命周期回调
- onCreate():在首次创建UIAbility实例时,系统触发onCreate()回调。开发者可以在该回调中执行UIAbility整个生命周期中仅发生一次的启动逻辑。
- onWindowStageCreate():UIAbility实例创建完成之后,在进入前台之前,系统会创建一个WindowStage。WindowStage创建完成后会进入onWindowStageCreate()回调,开发者可以在该回调中进行UI加载、WindowStage的事件订阅。
在onWindowStageCreate()回调中通过loadContent()方法设置应用要加载的页面,并根据需要调用on('windowStageEvent')方法订阅WindowStage的事件(获焦/失焦、切到前台/切到后台、前台可交互/前台不可交互)。
javascript
// 窗口舞台创建时调用
onWindowStageCreate(windowStage: window.WindowStage): void {
// 设置WindowStage的事件订阅(获焦/失焦、切到前台/切到后台、前台可交互/前台不可交互)
try {
windowStage.on('windowStageEvent', (data) => {
let stageEventType: window.WindowStageEventType = data;
switch (stageEventType) {
case window.WindowStageEventType.SHOWN: // 切到前台
hilog.info(DOMAIN, 'testTag', `windowStage foreground.`);
break;
case window.WindowStageEventType.ACTIVE: // 获焦状态
hilog.info(DOMAIN, 'testTag', `windowStage active.`);
break;
case window.WindowStageEventType.INACTIVE: // 失焦状态
hilog.info(DOMAIN, 'testTag', `windowStage inactive.`);
break;
case window.WindowStageEventType.HIDDEN: // 切到后台
hilog.info(DOMAIN, 'testTag', `windowStage background.`);
break;
case window.WindowStageEventType.RESUMED: // 前台可交互状态
hilog.info(DOMAIN, 'testTag', `windowStage resumed.`);
break;
case window.WindowStageEventType.PAUSED: // 前台不可交互状态
hilog.info(DOMAIN, 'testTag', `windowStage paused.`);
break;
default:
break;
}
});
} catch (exception) {
hilog.error(DOMAIN, 'testTag',
`Failed to enable the listener for window stage event changes. Cause: ${JSON.stringify(exception)}`);
}
// Main window is created, set main page for this ability
hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageCreate');
// 设置UI加载内容
windowStage.loadContent('pages/Index', (err) => {
if (err.code) {
hilog.error(DOMAIN, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err));
return;
}
hilog.info(DOMAIN, 'testTag', 'Succeeded in loading the content.');
});
}
-
onForeground() : 在UIAbility切换至前台时且UIAbility的UI可见之前,系统触发onForeground回调。开发者可以在该回调中申请系统需要的资源,或者重新申请在onBackground()中释放的资源。
例如,应用已获得地理位置权限。在UI显示之前,开发者可以在onForeground()回调中开启定位功能,从而获取到当前的位置信息。
-
onBackground() :在UIAbility的UI完全不可见之后,系统触发onBackground回调,将UIAbility实例切换至后台状态。开发者可以在该回调中释放UI不可见时的无用资源,例如停止定位功能,以节省系统的资源消耗。不能做耗时操作
-
onWindowStageWillDestroy(): 在UIAbility实例销毁之前,系统触发onWindowStageWillDestroy()回调。该回调在WindowStage销毁前执行,此时WindowStage可以使用。开发者可以在该回调中释放通过WindowStage获取的资源、注销WindowStage事件订阅等。
javascript
// 释放通过windowStage对象获取的资源
onWindowStageWillDestroy(windowStage: window.WindowStage): void {
hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageWillDestroy');
try {
// 在onWindowStageWillDestroy()中注销WindowStage事件订阅(获焦/失焦、切到前台/切到后台、前台可交互/前台不可交互)
windowStage.off('windowStageEvent');
hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageWillDestroy,off windowStageEvent');
} catch (error) {
hilog.error(DOMAIN, 'testTag',
`Failed to disable the listener for windowStageEvent. error is ${JSON.stringify(error)}`);
}
}
- onWindowStageDestroy():在UIAbility实例销毁之前,系统触发onWindowStageDestroy()回调,开发者可以在该回调中释放UI资源。该回调在WindowStage销毁后执行,此时WindowStage不可以使用。
javascript
onWindowStageCreate(windowStage: window.WindowStage): void {
// 加载UI资源
}
onWindowStageDestroy() {
// 释放UI资源
}
- onDestroy(): 在UIAbility实例销毁之前,系统触发onDestroy回调。该回调是UIAbility接收到的最后一个生命周期回调,开发者可以在onDestroy()回调中进行系统资源的释放、数据的保存等操作。
- onNewWant():当应用的UIAbility实例已创建,再次调用方法启动该UIAbility实例时,系统触发该UIAbility的onNewWant()回调。开发者可以在该回调中更新要加载的资源和数据等,用于后续的UI展示。
三、应用配置文件深度解析
1、app.json5全局配置
javascript
{
"app": {
"bundleName": "com.zmf.tools",
"vendor": "example",
"versionCode": 1000000,
"versionName": "1.0.0",
"icon": "$media:layered_image",
"label": "$string:app_name"
}
}
- bundleName : 同Android的包名
- vendor:标识对应用开发厂商的描述,取值为长度不超过255字节的字符串。该标签可用于展示开发厂商信息,如在应用的关于页面,取该标签展示开发厂商信息。
- versionCode:版本号,正整数
- versionName:向用户展示的应用版本号
- icon:应用的图标
- label:应用的名称
2、module.json5模块配置
javascript
{
"module": {
"name": "entry",
"type": "entry",
"description": "$string:module_desc",
"mainElement": "EntryAbility",
"deviceTypes": [
"phone"
],
"deliveryWithInstall": true,
"installationFree": false,
"pages": "$profile:main_pages",
"abilities": [
{
"name": "EntryAbility",
"srcEntry": "./ets/entryability/EntryAbility.ets",
"description": "$string:EntryAbility_desc",
"icon": "$media:layered_image",
"label": "$string:EntryAbility_label",
"startWindowIcon": "$media:startIcon",
"startWindowBackground": "$color:start_window_background",
"exported": true,
"skills": [
{
"entities": [
"entity.system.home"
],
"actions": [
"ohos.want.action.home"
]
}
]
}
],
"extensionAbilities": [
{
"name": "EntryBackupAbility",
"srcEntry": "./ets/entrybackupability/EntryBackupAbility.ets",
"type": "backup",
"exported": false,
"metadata": [
{
"name": "ohos.extension.backup",
"resource": "$profile:backup_config"
}
],
}
]
}
}
- module字段:模块基本信息
- abilities字段:标识当前Module中UIAbility的配置信息,只对当前UIAbility生效。
- requestPermissions字段:标识当前应用运行时需向系统申请的权限集合。
四、权限系统详解
1、权限分类
| 权限类型 | 授权方式 | 操作路径 |
|---|---|---|
| 开放权限(系统授权) | system_grant | 声明权限 > 访问接口 |
| 开放权限(用户授权) | user_grant | 声明权限 > 向用户申请授权 > 访问接口 |
| 受限开放权限 | system_grant | 申请使用受限权限 > 声明权限 > 访问接口 |
| 受限开放权限 | user_grant | 申请使用受限权限 > 声明权限 > 向用户申请授权 > 访问接口 |
2、常用权限示例
应用必须在module.json5配置文件的requestPermissions标签中声明权限。
bash
"requestPermissions": [
{
"name": "ohos.permission.INTERNET"
},
{
"name": "ohos.permission.GET_NETWORK_INFO"
},
{
"name": "ohos.permission.GET_WIFI_INFO"
},
{
"name": "ohos.permission.PUBLISH_AGENT_REMINDER"
},
{
"name": "ohos.permission.VIBRATE",
},
{
"name": 'ohos.permission.MICROPHONE',
"reason": '$string:ohos_permission_MICROPHONE',
"usedScene": {
"when": "always"
}
}
],
当应用需要访问用户的隐私信息或使用系统能力时,如获取位置信息、访问日历、使用相机拍摄照片或录音等,应向用户申请授权。这些权限属于user_grant权限。
当应用申请user_grant权限时,需完成以下步骤:
-
在配置文件中,声明应用需要请求的权限。
-
将应用中需要申请权限的目标对象与对应权限关联,确保用户明确哪些操作需授予应用指定权限。
-
运行应用时,用户触发访问目标对象时应调用接口,精准触发动态授权弹框。接口内部会检查当前用户是否已授权所需权限,若未授权,将拉起动态授权弹框请求用户授权。
-
检查用户的授权结果,确认用户已授权后,再进行下一步操作。
3、动态权限申请流程
javascript
permissions: Array<Permissions> = ['ohos.permission.MICROPHONE'];
// 使用UIExtensionAbility:将common.UIAbilityContext 替换为common.UIExtensionContext
reqPermissionsFromUser(permissions: Array<Permissions>, context: common.UIAbilityContext): void {
let atManager: abilityAccessCtrl.AtManager = abilityAccessCtrl.createAtManager();
// requestPermissionsFromUser会判断权限的授权状态来决定是否唤起弹窗
atManager.requestPermissionsFromUser(context, permissions).then(async (data) => {
let grantStatus: Array<number> = data.authResults;
let length: number = grantStatus.length;
for (let i = 0; i < length; i++) {
if (grantStatus[i] === 0) {
// 用户授权,可以继续访问目标操作
await this.startRecordingProcess()
} else {
return;
}
}
// 授权成功
}).catch((err: BusinessError) => {
console.error(`Failed to request permissions from user. Code is ${err.code}, message is ${err.message}`);
})
}
五、HAP、HAR、HSP概念辨析
1、HAP(HarmonyOS Ability Package):可独立部署的运行包
1)基本概念
HAP(Harmony Ability Package)是应用安装和运行的基本单元
HAP包是由代码、资源、第三方库、配置文件等打包生成的模块包,其主要分为两种类型:entry和feature。
- entry:应用的主模块,作为应用的入口,提供了应用的基础功能
- feature:应用的动态特性模块,作为应用能力的扩展,可以根据用户的需求和设备类型进行选择性安装。
2)使用场景
-
单HAP场景:如果只包含UIAbility组件,无需使用ExtensionAbility组件,优先采用单HAP(即一个entry包)来实现应用开发。推荐采用"一个UIAbility+多个页面"的方式。
-
多HAP场景:如果应用的功能比较复杂,需要使用ExtensionAbility组件,可以采用多HAP(即一个entry包+多个feature包)来实现应用开发,每个HAP中包含一个UIAbility组件或者一个ExtensionAbility组件。在这种场景下,多个HAP引用相同的库文件,可能导致重复打包的问题。
3)创建
-
创建工程,构建第一个ArkTS应用。
-
在工程目录上单击右键,选择New > Module。
-
在弹出的对话框中选择Empty Ability模板,单击Next。
-
在Module配置界面,配置Module name,选择Module Type和Device Type,然后单击Next。
-
在Ability配置界面,配置Ability name,然后单击Finish完成创建。



2、HAR(HarmonyOS Archive):静态共享包,编译时复制
1)基本概念
- HAR(Harmony Archive)是静态共享包,可以包含代码、C++库、资源和配置文件。通过HAR可以实现多个模块或多个工程共享ArkUI组件、资源等相关代码。
2)使用场景
- 支持应用内共享,也可以作为二方库(SDK)、三方库(SDK)发布后供其他应用使用。
- 作为二方库(SDK),发布到OHPM私仓,供公司内部其他应用使用。
- 作为三方库(SDK),发布到OHPM中心仓,供其他应用使用。
3)创建
- 鼠标移到工程目录顶部,单击右键,选择New > Module,在工程中添加模块。
- 在Choose Your Ability Template界面中,选择Static Library,并单击Next。


代码结构如下:

3、HSP(HarmonyOS Shared Package):动态共享包,运行时共享
1)基本概念
- DevEco Studio支持开发动态共享包HSP(Harmony Shared Package)
- 在应用/元服务开发过程中部分功能按需动态下载,或开发元服务场景时需要分包加载,可使用HSP实现相应功能。
- 当有多个安装包需要资源共享时,也可利用HSP减少公共资源和代码重复打包。
2)创建
- 方法1:鼠标移到工程目录顶部,单击鼠标右键,选择New > Module,开始创建新的Module。
- 方法2:选中工程目录中任意文件,然后在菜单栏选择File > New > Module,开始创建新的Module。
- 模板类型选择Shared Library,点击Next。


整个项目结构如下:
