UIAbility
# UIAbility组件概念
UIAbility组件是一种包括UI界面的应用组件,主要用于和用户交互。 UIAbility组件是系统调度的基本单元,为应用提供绘制界面的窗口,一个UIAbility组件中可以通过多个页面来实现一个功能模块。每一个UIAbility组件实例,都对应于一个最近的任务列表中的任务。
# 声明配置
为使应用能够正常使用UIAbility, 需要在module.json5
配置文件的abilities标签中声明UIAbility的名称、入口、标签等相关信息。
{
"module": {
//...
"abilities": [
{
"name": "EntryAbility", // UIAbility 组件的名称
"srcEntry": "./ets/entryability/EntryAbility.ts", // 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组件声明周期
当用户打开、切换和返回到对应应用时,应用中的UiAbility组件实例会在其生命周期的不同状态进行转换。
UIAbility组件包括四个生命周期: Create、 Foreground、 Background、 Destroy
# Create 状态
该状态是在应用加载过程中,UIAbility实例创建完成时触发,系统会调用onCreate()回调。可以在该回调中进行页面初始化操作,例如变量定义资源加载等,用于后续的UI界面展示
import UIAbility from '@ohos.app.ability.UIAbility';
import Window from '@ohos.window';
export default class EntryAbility extends UIAbility {
onCreate(want, launchParam) {
// 页面初始化
}
// ...
}
# windowStageCreate 和 windowStageDestroy 状态
UIAbility实例在进入到 Create之后,进入Foreground之前,系统会创建一个windowStage。
WindowStage创建完成以后,会进入到onWindowStageCreate() 回调,可以在这个时期设置UI界面加载、设置WindowStage的事件订阅。
在onWindowStageCreate()
回调里加载loadContent
方法指定加载的页面,并根据需要订阅WindowStage事件(获焦/失焦、可见/不可见)
# Foreground和Background状态
Foreground 和Background在UIAbility实例切换到前台和后台时触发。对应于onForeground 和onBackground回调
import UIAbility from '@ohos.app.ability.UIAbility';
export default class EntryAbility extends UIAbility {
onForeground() {
// 申请系统需要的资源,或者重新申请在onBackground中释放的资源
}
onBackground() {
// 释放UI界面不可见时无用的资源,或者在此回调中执行较为耗时的操作
// 例如状态保存等
}
}
# Destroy
Destroy状态在UIAbility实例销毁时触发。可以在onDestroy()回调中进行系统资源的释放、数据的保存等操作。
import UIAbility from '@ohos.app.ability.UIAbility';
export default class EntryAbility extends UIAbility {
onDestroy() {
// 系统资源的释放、数据的保存等
}
}
完整UIAbility示例:
import UIAbility from '@ohos.app.ability.UIAbility';
import hilog from '@ohos.hilog';
import window from '@ohos.window';
export default class EntryAbility extends UIAbility {
onCreate(want, launchParam) {
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate');
}
onDestroy() {
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onDestroy');
}
onWindowStageCreate(windowStage: window.WindowStage) {
// Main window is created, set main page for this ability
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate');
windowStage.loadContent('pages/Index', (err, data) => {
if (err.code) {
hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? '');
return;
}
hilog.info(0x0000, 'testTag', 'Succeeded in loading the content. Data: %{public}s', JSON.stringify(data) ?? '');
});
}
onWindowStageDestroy() {
// Main window is destroyed, release UI related resources
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageDestroy');
}
onForeground() {
// Ability has brought to foreground
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onForeground');
}
onBackground() {
// Ability has back to background
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onBackground');
}
}
# UIAbility组件启动模式
三种模块:
- singleton(单实例模式)
- multition(多实例模式)
- specified(指定实例模式)
{
"module": {
// ...
"abilities": [
{
"launchType": "singleton",
// ...
}
]
}
}
# singleton(单实例模式)
每次调用startAbility()方法时,如果应用进程中该类型的UIAbility实例已经存在,则复用系统中的UIAbility实例。
系统中只存在一个UIAbility实例
# multition(多实例模式)
multition 启动模式 为多实例模式,每次调用startAbility() 方法时,都会在进程中创建一个新的该类型UIAbility实例。
# specified(指定实例模式)
specified启动模式为指定实例模式,针对一些特殊场景使用(例如文档应用中每次新建文档希望都能新建一个文档实例,重复打开一个已保存的文档希望打开的是同一个文档实例)
每个实例绑定一个唯一的key(instanceKey),如果匹配有该UIAbility实例的Key,则直接拉起与之绑定的UIAbility 实例。否则创建一个新的UIAbility实例。
// 在启动指定实例模式的UIAbility时,给每一个UIAbility实例配置一个独立的Key标识
// 例如在文档使用场景中,可以用文档路径作为Key标识
function getInstance() {
// ...
}
let want = {
deviceId: '', // deviceId为空表示本设备
bundleName: 'com.example.myapplication',
abilityName: 'FuncAbility',
moduleName: 'module1', // moduleName非必选
parameters: { // 自定义信息
instanceKey: getInstance(),
},
}
// context为调用方UIAbility的AbilityContext
this.context.startAbility(want).then(() => {
// ...
}).catch((err) => {
// ...
})
# UIAbility 组件基本用法
指定UIAbility 启动页面和获取UIAbility上下文UIAbilityContext
# 指定UIAbility的启动页面
应用中的UIAbility在启动过程中,需要指定启动页面,否则应用启动后会因为没有加载默认页面而白屏
在UIAbility的 onWindowStageCreate() 调用loadContent() 设置启动页面
import UIAbility from '@ohos.app.ability.UIAbility';
import Window from '@ohos.window';
export default class EntryAbility extends UIAbility {
onWindowStageCreate(windowStage: Window.WindowStage) {
// Main window is created, set main page for this ability
windowStage.loadContent('pages/Index', (err, data) => {
// ...
});
}
// ...
}
# 获取UIAbility的上下文信息
通过UIAbilityContext可以获取UIAbility的相关配置信息,如包代码路径、Bundle名称、Ability名称和应用程序需要的环境状态等属性信息,以及可以获取操作UIAbility实例的方法(如startAbility()、connectServiceExtensionAbility()、terminateSelf()等)
- 在UIAbility中可以通过this.context获取UIAbility实例的上下文信息。
import UIAbility from '@ohos.app.ability.UIAbility';
export default class EntryAbility extends UIAbility {
onCreate(want, launchParam) {
// 获取UIAbility实例的上下文
let context = this.context;
// ...
}
}
- 在页面中获取UIAbility实例的上下文信息,包括导入依赖资源context模块和在组件中定义一个context变量两个部分。
import common from '@ohos.app.ability.common';
@Entry
@Component
struct Index {
private context = getContext(this) as common.UIAbilityContext;
startAbilityTest() {
let want = {
// Want参数信息
};
this.context.startAbility(want);
}
// 页面展示
build() {
// ...
}
}
import common from '@ohos.app.ability.common';
@Entry
@Component
struct Index {
startAbilityTest() {
let context = getContext(this) as common.UIAbilityContext;
let want = {
// Want参数信息
};
context.startAbility(want);
}
// 页面展示
build() {
// ...
}
}
# UIAbility组件与UI的数据同步
使用EventHub进行数据通信:基于发布订阅模式来实现,事件需要先订阅后发布,订阅者收到消息后进行处理。
使用globalThis进行数据同步:ArkTS引擎实例内部的一个全局对象,在ArkTS引擎实例内部都能访问。
使用AppStorage/LocalStorage进行数据同步:ArkUI提供了AppStorage和LocalStorage两种应用级别的状态管理方案,可用于实现应用级别和UIAbility级别的数据同步。
# 使用EventHub进行数据通信
执行订阅操作
import UIAbility from '@ohos.app.ability.UIAbility';
const TAG: string = '[Example].[Entry].[EntryAbility]';
export default class EntryAbility extends UIAbility {
func1(...data) {
// 触发事件,完成相应的业务操作
console.info(TAG, '1. ' + JSON.stringify(data));
}
onCreate(want, launch) {
// 获取eventHub
let eventhub = this.context.eventHub;
// 执行订阅操作
eventhub.on('event1', this.func1);
eventhub.on('event1', (...data) => {
// 触发事件,完成相应的业务操作
console.info(TAG, '2. ' + JSON.stringify(data));
});
}
}
触发该事件
import common from '@ohos.app.ability.common';
@Entry
@Component
struct Index {
private context = getContext(this) as common.UIAbilityContext;
eventHubFunc() {
// 不带参数触发自定义“event1”事件
this.context.eventHub.emit('event1');
// 带1个参数触发自定义“event1”事件
this.context.eventHub.emit('event1', 1);
// 带2个参数触发自定义“event1”事件
this.context.eventHub.emit('event1', 2, 'test');
// 开发者可以根据实际的业务场景设计事件传递的参数
}
// 页面展示
build() {
// ...
}
}
# 使用globalThis进行数据同步
使用globalThis进行数据同步
使用:
//数据存入globalThis中
globalThis.xxx= [数据];
//需要使用的地方调用
let a = globalThis.xxx
UIAbility和UIAbility之间使用globalThis 使用的注意事项
- 存放名称不要相同,Stage模型下进程内的UIAbility组件共享ArkTS引擎实例,使用globalThis时需要避免存放相同名称的对象。例如AbilityA和AbilityB可以使用globalThis共享数据,在存放相同名称的对象时,先存放的对象会被后存放的对象覆盖。
- 用完将其赋值为null,以减少对应用内存的占用。对于绑定在globalThis上的对象,其生命周期与ArkTS虚拟机实例相同,建议在使用完成之后将其赋值为null,以减少对应用内存的占用。
# 使用AppStorage/LocalStorage进行数据同步
- AppStorage:是全局状态管理器,适应于 多个 UIAbility 共享同一份数据的情况
- LocalStorage:是局部状态管理器,适应于单个UIAbility 内部使用的状态数据
# UiAbility组件内交互(设备内)
UIAbility 是系统调度的最小单元,在设备内的功能模块跳转时,会涉及到启动的特定的UIAbility,该UIAbility 应该是应用内的其他UIAbility,也可以是其他应用的UIAbility(比如第三方支付)
# 启动应用内的UIAbility
let wantInfo = {
deviceId: '', // deviceId为空表示本设备
bundleName: 'com.example.myapplication',
abilityName: 'FuncAbility',
moduleName: 'module1', // moduleName非必选
parameters: { // 自定义信息
info: '来自EntryAbility Index页面',
},
}
// context为调用方UIAbility的AbilityContext
this.context.startAbility(wantInfo).then(() => {
// ...
}).catch((err) => {
// ...
})
接受参数
import UIAbility from '@ohos.app.ability.UIAbility';
import Window from '@ohos.window';
export default class FuncAbility extends UIAbility {
onCreate(want, launchParam) {
// 接收调用方UIAbility传过来的参数
let funcAbilityWant = want;
let info = funcAbilityWant?.parameters?.info;
// ...
}
}
停止当前UIAbility实例
// context为需要停止的UIAbility实例的AbilityContext
this.context.terminateSelf((err) => {
// ...
});
# 启动应用内的UIAbility并获取返回结果
let wantInfo = {
deviceId: '', // deviceId为空表示本设备
bundleName: 'com.example.myapplication',
abilityName: 'FuncAbility',
moduleName: 'module1', // moduleName非必选
parameters: { // 自定义信息
info: '来自EntryAbility Index页面',
},
}
// context为调用方UIAbility的AbilityContext
this.context.startAbilityForResult(wantInfo).then((data) => {
// ...
}).catch((err) => {
// ...
})
const RESULT_CODE: number = 1001;
let abilityResult = {
resultCode: RESULT_CODE,
want: {
bundleName: 'com.example.myapplication',
abilityName: 'FuncAbility',
moduleName: 'module1',
parameters: {
info: '来自FuncAbility Index页面',
},
},
}
// context为被调用方UIAbility的AbilityContext
this.context.terminateSelfWithResult(abilityResult, (err) => {
// ...
});
const RESULT_CODE: number = 1001;
// ...
// context为调用方UIAbility的AbilityContext
this.context.startAbilityForResult(want).then((data) => {
if (data?.resultCode === RESULT_CODE) {
// 解析被调用方UIAbility返回的信息
let info = data.want?.parameters?.info;
// ...
}
}).catch((err) => {
// ...
})
# 启动其他应用的UIAbility
启动UIAbility 有显式启动和隐式启动 两种
显式Want启动:启动一个确定应用的UIAbility,在want参数中需要设置该应用bundleName和abilityName,当需要拉起某个明确的UIAbility时,通常使用显式Want启动方式。
隐式启动:根据匹配条件由用户选择启动哪个UIAbility,不明确指出要启动哪一个UIAbility(abilityName参数未设置)
# 启动其他应用的UIAbility并获取返回结果
# 启动UIAbility的指定页面
# 调用方UIAbility指定启动页面
let wantInfo = {
deviceId: '', // deviceId为空表示本设备
bundleName: 'com.example.myapplication',
abilityName: 'FuncAbility',
moduleName: 'module1', // moduleName非必选
parameters: { // 自定义参数传递页面信息
router: 'funcA',
},
}
// context为调用方UIAbility的AbilityContext
this.context.startAbility(wantInfo).then(() => {
// ...
}).catch((err) => {
// ...
})
# 目标UIAbility首次启动
import UIAbility from '@ohos.app.ability.UIAbility'
import Window from '@ohos.window'
export default class FuncAbility extends UIAbility {
funcAbilityWant;
onCreate(want, launchParam) {
// 接收调用方UIAbility传过来的参数
this.funcAbilityWant = want;
}
onWindowStageCreate(windowStage: Window.WindowStage) {
// Main window is created, set main page for this ability
let url = 'pages/Index';
if (this.funcAbilityWant?.parameters?.router) {
if (this.funcAbilityWant.parameters.router === 'funcA') {
url = 'pages/Second';
}
}
windowStage.loadContent(url, (err, data) => {
// ...
});
}
}
# 目标UIAbility非首次启动
import UIAbility from '@ohos.app.ability.UIAbility'
export default class FuncAbility extends UIAbility {
onNewWant(want, launchParam) {
// 接收调用方UIAbility传过来的参数
globalThis.funcAbilityWant = want;
// ...
}
}
import router from '@ohos.router';
@Entry
@Component
struct Index {
onPageShow() {
let funcAbilityWant = globalThis.funcAbilityWant;
let url2 = funcAbilityWant?.parameters?.router;
if (url2 && url2 === 'funcA') {
router.replaceUrl({
url: 'pages/Second',
})
}
}
// 页面展示
build() {
// ...
}
}
提示
当被调用方Ability的启动模式设置为multiton启动模式时,每次启动都会创建一个新的实例,那么onNewWant()回调就不会被用到。