UIAbility 组件概述
UIAbility 组件是一种包含 UI 的应用组件,主要用于和用户交互。
UIAbility 的设计理念:
原生支持应用组件级的跨端迁移和多端协同。
支持多设备和多窗口形态。
UIAbility 划分原则与建议:
UIAbility 组件是系统调度的基本单元,为应用提供绘制界面的窗口。一个应用可以包含一个或多个 UIAbility 组件。例如,在支付应用中,可以将入口功能和收付款功能分别配置为独立的 UIAbility。
每一个 UIAbility 组件实例都会在最近任务列表中显示一个对应的任务。
对于开发者而言,可以根据具体场景选择单个还是多个 UIAbility,划分建议如下:
如果开发者希望在任务视图中看到一个任务,则建议使用一个 UIAbility,多个页面的方式。
如果开发者希望在任务视图中看到多个任务,或者需要同时开启多个窗口,则建议使用多个 UIAbility 开发不同的模块功能。
声明配置
为使应用能够正常使用 UIAbility,需要在 module.json5 配置文件的 abilities 标签中声明 UIAbility 的名称、入口、标签等相关信息。
{
"module": {
// ...
"abilities": [
{
"name": "EntryAbility", // UIAbility组件的名称
"srcEntry": "./ets/entryability/EntryAbility.ets", // UIAbility组件的代码路径
"description": "$string:EntryAbility_desc", // UIAbility组件的描述信息
"icon": "$media:icon", // UIAbility组件的图标
"label": "$string:EntryAbility_label", // UIAbility组件的标签
"startWindowIcon": "$media:icon", // UIAbility组件启动页面图标资源文件的索引
"startWindowBackground": "$color:start_window_background", // UIAbility组件启动页面背景颜色资源文件的索引
// ...
}
]
}
}
UIAbility 与 WindowStage 关系
UIAbility 可以理解为一个进程
WindowStage 则是这个进程里面的一个窗口,用于承载应用中的 UI 组件。
UIAbility 组件生命周期(冷)
冷启动 就是说应用进程不存在,需要重新创建进程,并启动应用
热启动 就是说应用进程存在,只需要重新启动应用
概述
当用户打开、切换和返回到对应应用时,应用中的 UIAbility 实例会在其生命周期的不同状态之间转换。UIAbility 类提供了一系列回调,通过这些回调可以知道当前 UIAbility 实例的某个状态发生改变,会经过 UIAbility 实例的创建和销毁,或者 UIAbility 实例发生了前后台的状态切换。
UIAbility 的生命周期包括 Create、Foreground、Background、Destroy 四个状态,如下图所示。
Create 状态
Create 状态为在应用加载过程中,UIAbility
实例创建完成时触发,系统会调用 onCreate()
回调。可以在该回调中进行页面初始化操作,例如变量定义资源加载等,用于后续的 UI 展示。
import { AbilityConstant, UIAbility, Want } from "@kit.AbilityKit";
export default class EntryAbility extends UIAbility {
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
// 页面初始化
}
// ...
}
INFO
Want 是对象间信息传递的载体,可以用于应用组件间的信息传递
WindowStageCreate 和 WindowStageDestroy 状态
UIAbility 实例创建完成之后,在进入 Foreground 之前,系统会创建一个 WindowStage。WindowStage 创建完成后会进入 onWindowStageCreate()回调,可以在该回调中设置 UI 加载、设置 WindowStage 的事件订阅。
在 onWindowStageCreate()
回调中通过 loadContent()
方法设置应用要加载的页面,并根据需要调用 on('windowStageEvent')
方法订阅 WindowStage 的事件(获焦/失焦、可见/不可见)
import { UIAbility } from "@kit.AbilityKit";
import { window } from "@kit.ArkUI";
import { hilog } from "@kit.PerformanceAnalysisKit";
const TAG: string = "[EntryAbility]";
const DOMAIN_NUMBER: number = 0xff00;
export default class EntryAbility extends UIAbility {
// ...
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_NUMBER, TAG, "windowStage foreground.");
break;
case window.WindowStageEventType.ACTIVE: // 获焦状态
hilog.info(DOMAIN_NUMBER, TAG, "windowStage active.");
break;
case window.WindowStageEventType.INACTIVE: // 失焦状态
hilog.info(DOMAIN_NUMBER, TAG, "windowStage inactive.");
break;
case window.WindowStageEventType.HIDDEN: // 切到后台
hilog.info(DOMAIN_NUMBER, TAG, "windowStage background.");
break;
default:
break;
}
});
} catch (exception) {
hilog.error(
DOMAIN_NUMBER,
TAG,
"Failed to enable the listener for window stage event changes. Cause:" +
JSON.stringify(exception)
);
}
hilog.info(DOMAIN_NUMBER, TAG, "%{public}s", "Ability onWindowStageCreate");
// 设置UI加载
windowStage.loadContent("pages/Index", (err, data) => {
// ...
});
}
}
对应于 onWindowStageCreate()
回调。在 UIAbility 实例销毁之前,则会先进入 onWindowStageDestroy()
回调,可以在该回调中释放 UI 资源。
import { UIAbility } from '@kit.AbilityKit';
import { window } from '@kit.ArkUI';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { BusinessError } from '@kit.BasicServicesKit';
const TAG: string = '[EntryAbility]';
const DOMAIN_NUMBER: number = 0xFF00;
export default class EntryAbility extends UIAbility {
windowStage: window.WindowStage | undefined = undefined;
// ...
onWindowStageCreate(windowStage: window.WindowStage): void {
this.windowStage = windowStage;
// ...
}
onWindowStageDestroy() {
// 释放UI资源
// 例如在onWindowStageDestroy()中注销获焦/失焦等WindowStage事件
try {
if (this.windowStage) {
this.windowStage.off('windowStageEvent');
}
} catch (err) {
let code = (err as BusinessError).code;
let message = (err as BusinessError).message;
hilog.error(DOMAIN_NUMBER, TAG, `Failed to disable the listener for windowStageEvent. Code is ${code}, message is ${message}`);
}
}
}
WindowStageWillDestroy 状态
对应 onWindowStageWillDestroy()回调,在 WindowStage 销毁前执行,此时 WindowStage 可以使用。
import { UIAbility } from "@kit.AbilityKit";
import { window } from "@kit.ArkUI";
export default class EntryAbility extends UIAbility {
windowStage: window.WindowStage | undefined = undefined;
// ...
onWindowStageCreate(windowStage: window.WindowStage): void {
this.windowStage = windowStage;
// ...
}
onWindowStageWillDestroy(windowStage: window.WindowStage) {
// 释放通过windowStage对象获取的资源
}
onWindowStageDestroy() {
// 释放UI资源
}
}
Foreground 和 Background 状态
Foreground 和 Background 状态分别在 UIAbility 实例切换至前台和切换至后台时触发,对应于 onForeground()回调和 onBackground()回调。
onForeground()回调,在 UIAbility 的 UI 可见之前,如 UIAbility 切换至前台时触发。可以在 onForeground()回调中申请系统需要的资源,或者重新申请在 onBackground()中释放的资源。
onBackground()回调,在 UIAbility 的 UI 完全不可见之后,如 UIAbility 切换至后台时候触发。可以在 onBackground()回调中释放 UI 不可见时无用的资源,或者在此回调中执行较为耗时的操作,例如状态保存等。
例如应用在使用过程中需要使用用户定位时,假设应用已获得用户的定位权限授权。在 UI 显示之前,可以在 onForeground()回调中开启定位功能,从而获取到当前的位置信息。
当应用切换到后台状态,可以在 onBackground()回调中停止定位功能,以节省系统的资源消耗。
import { UIAbility } from "@kit.AbilityKit";
export default class EntryAbility extends UIAbility {
// ...
onForeground(): void {
// 申请系统需要的资源,或者重新申请在onBackground()中释放的资源
}
onBackground(): void {
// 释放UI不可见时无用的资源,或者在此回调中执行较为耗时的操作
// 例如状态保存等
}
}
当应用的 UIAbility 实例已创建,且 UIAbility 配置为 单例 启动模式时,再次调用 startAbility()
方法启动该 UIAbility 实例时,只会进入该 UIAbility 的 onNewWant()
回调,不会进入其 onCreate()
和 onWindowStageCreate()
生命周期回调。应用可以在该回调中更新要加载的资源和数据等,用于后续的 UI 展示。
import { AbilityConstant, UIAbility, Want } from "@kit.AbilityKit";
export default class EntryAbility extends UIAbility {
// ...
onNewWant(want: Want, launchParam: AbilityConstant.LaunchParam) {
// 更新资源、数据
}
}
Destroy 状态
Destroy 状态在 UIAbility 实例销毁时触发。可以在 onDestroy()回调中进行系统资源的释放、数据的保存等操作。
例如调用 terminateSelf()
方法停止当前 UIAbility 实例,从而完成 UIAbility 实例的销毁;或者用户使用最近任务列表关闭该 UIAbility 实例,完成 UIAbility 的销毁。
import { UIAbility } from "@kit.AbilityKit";
export default class EntryAbility extends UIAbility {
// ...
onDestroy() {
// 系统资源的释放、数据的保存等
}
}
UIAbility 生命周期(热启动)
热启动就是两个生命生命周期会被一个生命周期替换掉.如图所示
- 举例如下 一般热启动与 windowStage 里面的 onAccept 一起使用
import { AbilityConstant, Want, UIAbility } from "@kit.AbilityKit";
import { hilog } from "@kit.PerformanceAnalysisKit";
import type { Router, UIContext } from "@kit.ArkUI";
import type { BusinessError } from "@kit.BasicServicesKit";
const DOMAIN_NUMBER: number = 0xff00;
const TAG: string = "[EntryAbility]";
export default class EntryAbility extends UIAbility {
funcAbilityWant: Want | undefined = undefined;
uiContext: UIContext | undefined = undefined;
// ...
onNewWant(want: Want, launchParam: AbilityConstant.LaunchParam): void {
if (want?.parameters?.router && want.parameters.router === "funcA") {
let funcAUrl = "pages/Page_HotStartUp";
if (this.uiContext) {
let router: Router = this.uiContext.getRouter();
router
.pushUrl({
url: funcAUrl,
})
.catch((err: BusinessError) => {
hilog.error(
DOMAIN_NUMBER,
TAG,
`Failed to push url. Code is ${err.code}, message is ${err.message}`
);
});
}
}
}
}