HarmonyOS NEXT: UIAbility进阶
一个UIAbility可以对应多个页面,在不同的场景下启动该UIAbility时需要展示不同的页面,例如从一个UIAbility的页面中跳转到另外一个UIAbility时,希望启动目标UIAbility的指定页面。UIAbility的启动分为两种情况:UIAbility冷启动和UIAbility热启动。UIAbility冷启动:指的是UIAbility实例处于完全关闭状态下被启动,这需要完整地加载
AbilityStage组件容器介绍
AbilityStage是一个Module级别的组件容器,应用的HAP在首次加载时会创建一个AbilityStage实例,可以对该Module进行初始化等操作。
AbilityStage与Module一一对应,即一个Module拥有一个AbilityStage。
DevEco Studio默认工程中未自动生成AbilityStage,如需要使用AbilityStage的能力,可以手动新建一个AbilityStage文件,具体步骤如下。
-
在工程Module对应的ets目录下,右键选择“New > Directory”,新建一个目录并命名为myabilitystage。
-
在myabilitystage目录,右键选择“New > ArkTS File”,新建一个文件并命名为MyAbilityStage.ets。
-
打开MyAbilityStage.ets文件,导入AbilityStage的依赖包,自定义类继承AbilityStage并加上需要的生命周期回调,示例中增加了一个onCreate()生命周期回调。
import { AbilityStage, Want } from '@kit.AbilityKit';
export default class MyAbilityStage extends AbilityStage {
onCreate(): void {
// 应用HAP首次加载时触发,可以在此执行该Module的初始化操作(例如资源预加载、线程创建等)。
}
onAcceptWant(want: Want): string {
// 仅specified模式下触发
return 'MyAbilityStage';
}
}
4. 在module.json5配置文件中,通过配置 srcEntry 参数来指定模块对应的代码路径,以作为HAP加载的入口。
{
"module": {
"name": "entry",
"type": "entry",
"srcEntry": "./ets/myabilitystage/MyAbilityStage.ets",
// ...
}
}
AbilityStage拥有onCreate()生命周期回调和onAcceptWant()、onConfigurationUpdated()、onMemoryLevel()事件回调。
-
onCreate()生命周期回调:在开始加载对应Module的第一个UIAbility实例之前会先创建AbilityStage,并在AbilityStage创建完成之后执行其onCreate()生命周期回调。AbilityStage模块提供在Module加载的时候,通知开发者,可以在此进行该Module的初始化(如资源预加载,线程创建等)能力。
-
onAcceptWant()事件回调:UIAbility指定实例模式(specified)启动时候触发的事件回调,具体使用请参见UIAbility启动模式综述。
-
onConfigurationUpdated()事件回调:当系统全局配置发生变更时触发的事件,系统语言、深浅色等,配置项目前均定义在Configuration类中。
-
onMemoryLevel()事件回调:当系统调整内存时触发的事件。
应用被切换到后台时,系统会将在后台的应用保留在缓存中。即使应用处于缓存中,也会影响系统整体性能。当系统资源不足时,系统会通过多种方式从应用中回收内存,必要时会完全停止应用,从而释放内存用于执行关键任务。为了进一步保持系统内存的平衡,避免系统停止用户的应用进程,可以在AbilityStage中的onMemoryLevel()生命周期回调中订阅系统内存的变化情况,释放不必要的资源。
import { AbilityStage, AbilityConstant } from '@kit.AbilityKit';
export default class MyAbilityStage extends AbilityStage {
onMemoryLevel(level: AbilityConstant.MemoryLevel): void {
// 根据系统可用内存的变化情况,释放不必要的内存
}
}
UIAbility组件的启动模式
UIAbility的启动模式是指UIAbility实例在启动时的不同呈现状态。针对不同的业务场景,系统提供了三种启动模式:
- singleton(单实例模式)
- multiton(多实例模式)
- specified(指定实例模式)
说明
standard是multiton的曾用名,效果与多实例模式一致。
singleton启动模式
singleton启动模式为单实例模式,也是默认情况下的启动模式。
每次调用startAbility()方法时,如果应用进程中该类型的UIAbility实例已经存在,则复用系统中的UIAbility实例。系统中只存在唯一一个该UIAbility实例,即在最近任务列表中只存在一个该类型的UIAbility实例。
说明
应用的UIAbility实例已创建,该UIAbility配置为单实例模式,再次调用startAbility()方法启动该UIAbility实例。由于启动的还是原来的UIAbility实例,并未重新创建一个新的UIAbility实例,此时只会进入该UIAbility的onNewWant()回调,不会进入其onCreate()和onWindowStageCreate()生命周期回调。
如果需要使用singleton启动模式,在module.json5配置文件中的launchType字段配置为singleton即可。
{
"module": {
// ...
"abilities": [
{
"launchType": "singleton",
// ...
}
]
}
}
multiton启动模式
multiton启动模式为多实例模式,每次调用startAbility()方法时,都会在应用进程中创建一个新的该类型UIAbility实例。即在最近任务列表中可以看到有多个该类型的UIAbility实例。这种情况下可以将UIAbility配置为multiton(多实例模式)。
multiton启动模式的开发使用,在module.json5配置文件中的launchType字段配置为multiton即可。
{
"module": {
// ...
"abilities": [
{
"launchType": "multiton",
// ...
}
]
}
}
specified启动模式
specified启动模式为指定实例模式,针对一些特殊场景使用(例如文档应用中每次新建文档希望都能新建一个文档实例,重复打开一个已保存的文档希望打开的都是同一个文档实例)。
假设应用有两个UIAbility实例,即EntryAbility和SpecifiedAbility。EntryAbility以specified模式启动SpecifiedAbility。基本原理如下:
- EntryAbility调用startAbility()方法,并在Want的parameters字段中设置唯一的Key值,用于标识SpecifiedAbility。
- 系统在拉起SpecifiedAbility之前,会先进入对应的AbilityStage的onAcceptWant()生命周期回调,获取用于标识目标UIAbility的Key值。
- 系统会根据获取的Key值来匹配UIAbility。
- 如果匹配到对应的UIAbility,则会启动该UIAbility实例,并进入onNewWant()生命周期回调。
- 如果无法匹配对应的UIAbility,则会创建一个新的UIAbility实例,并进入该UIAbility实例的onCreate()生命周期回调和onWindowStageCreate()生命周期回调。
1.在SpecifiedAbility中,需要将module.json5配置文件的launchType字段配置为specified。
{
"module": {
// ...
"abilities": [
{
"launchType": "specified",
// ...
}
]
}
}
2.在EntryAbility中,调用startAbility()方法时,可以在want参数中传入了自定义参数instanceKey作为唯一标识符,以此来区分不同的UIAbility实例。示例中instanceKey的value值设置为字符串'KEY'。
// 在启动指定实例模式的UIAbility时,给每一个UIAbility实例配置一个独立的Key标识
// 例如在文档使用场景中,可以用文档路径作为Key标识
import { common, Want } from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { BusinessError } from '@kit.BasicServicesKit';
const TAG: string = '[Page_StartModel]';
const DOMAIN_NUMBER: number = 0xFF00;
function getInstance(): string {
return 'KEY';
}
@Entry
@Component
struct Page_StartModel {
private KEY_NEW = 'KEY';
build() {
Row() {
Column() {
// ...
Button()
.onClick(() => {
let context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext;
// context为调用方UIAbility的UIAbilityContext;
let want: Want = {
deviceId: '', // deviceId为空表示本设备
bundleName: 'com.samples.stagemodelabilitydevelop',
abilityName: 'SpecifiedFirstAbility',
moduleName: 'entry', // moduleName非必选
parameters: {
// 自定义信息
instanceKey: this.KEY_NEW
}
};
context.startAbility(want).then(() => {
hilog.info(DOMAIN_NUMBER, TAG, 'Succeeded in starting SpecifiedAbility.');
}).catch((err: BusinessError) => {
hilog.error(DOMAIN_NUMBER, TAG, `Failed to start SpecifiedAbility. Code is ${err.code}, message is ${err.message}`);
})
this.KEY_NEW = this.KEY_NEW + 'a';
})
// ...
Button()
.onClick(() => {
let context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext;
// context为调用方UIAbility的UIAbilityContext;
let want: Want = {
deviceId: '', // deviceId为空表示本设备
bundleName: 'com.samples.stagemodelabilitydevelop',
abilityName: 'SpecifiedSecondAbility',
moduleName: 'entry', // moduleName非必选
parameters: {
// 自定义信息
instanceKey: getInstance()
}
};
context.startAbility(want).then(() => {
hilog.info(DOMAIN_NUMBER, TAG, 'Succeeded in starting SpecifiedAbility.');
}).catch((err: BusinessError) => {
hilog.error(DOMAIN_NUMBER, TAG, `Failed to start SpecifiedAbility. Code is ${err.code}, message is ${err.message}`);
})
this.KEY_NEW = this.KEY_NEW + 'a';
})
// ...
}
.width('100%')
}
.height('100%')
}
}
根据业务在SpecifiedAbility的onAcceptWant()生命周期回调设置该UIAbility的标识。示例中标识设置为SpecifiedAbilityInstance_KEY。
import { AbilityStage, Want } from '@kit.AbilityKit';
export default class MyAbilityStage extends AbilityStage {
onAcceptWant(want: Want): string {
// 在被调用方的AbilityStage中,针对启动模式为specified的UIAbility返回一个UIAbility实例对应的一个Key值
// 当前示例指的是module1 Module的SpecifiedAbility
if (want.abilityName === 'SpecifiedFirstAbility' || want.abilityName === 'SpecifiedSecondAbility') {
// 返回的字符串KEY标识为自定义拼接的字符串内容
if (want.parameters) {
return `SpecifiedAbilityInstance_${want.parameters.instanceKey}`;
}
}
// ...
return 'MyAbilityStage';
}
}
说明
- 当应用的UIAbility实例已经被创建,并且配置为指定实例模式时,如果再次调用startAbility()方法启动该UIAbility实例,且AbilityStage的onAcceptWant()回调匹配到一个已创建的UIAbility实例,则系统会启动原来的UIAbility实例,并且不会重新创建一个新的UIAbility实例。此时,该UIAbility实例的onNewWant()回调会被触发,而不会触发onCreate()和onWindowStageCreate()生命周期回调。
- DevEco Studio默认工程中未自动生成AbilityStage,AbilityStage文件的创建请参见AbilityStage组件容器。
-
例如在文档应用中,可以为不同的文档实例内容绑定不同的Key值。每次新建文档时,可以传入一个新的Key值(例如可以将文件的路径作为一个Key标识),此时AbilityStage中启动UIAbility时都会创建一个新的UIAbility实例;当新建的文档保存之后,回到桌面,或者新打开一个已保存的文档,回到桌面,此时再次打开该已保存的文档,此时AbilityStage中再次启动该UIAbility时,打开的仍然是之前原来已保存的文档界面。
以如下步骤所示进行举例说明。
- 打开文件A,对应启动一个新的UIAbility实例,例如启动UIAbility实例1。
- 在最近任务列表中关闭文件A的任务进程,此时UIAbility实例1被销毁,回到桌面,再次打开文件A,此时对应启动一个新的UIAbility实例,例如启动UIAbility实例2。
- 回到桌面,打开文件B,此时对应启动一个新的UIAbility实例,例如启动UIAbility实例3。
- 回到桌面,再次打开文件A,此时仍然启动之前的UIAbility实例2,因为系统会自动匹配UIAbility实例的Key值,如果存在与之匹配的Key,则会启动与之绑定的UIAbility实例。在此例中,之前启动的UIAbility实例2与文件A绑定的Key是相同的,因此系统会拉回UIAbility实例2并让其获焦,而不会创建新的实例。
示例代码
UIAbility组件间的交互
UIAbility是系统调度的最小单元。在设备内的功能模块之间跳转时,会涉及到启动特定的UIAbility,包括应用内的其他UIAbility、或者其他应用的UIAbility(例如启动三方支付UIAbility)。
本文主要介绍启动应用内的UIAbility组件的方式。应用间的组件跳转详见应用间跳转。
- 启动应用内的UIAbility
- 启动应用内的UIAbility并获取返回结果
- 启动UIAbility的指定页面
启动应用内的UIAbility
当一个应用内包含多个UIAbility时,存在应用内启动UIAbility的场景。例如在支付应用中从入口UIAbility启动收付款UIAbility。
假设应用中有两个UIAbility:EntryAbility和FuncAbility(可以在同一个Module中,也可以在不同的Module中),需要从EntryAbility的页面中启动FuncAbility。
-
在EntryAbility中,通过调用startAbility()方法启动UIAbility,want为UIAbility实例启动的入口参数,其中bundleName为待启动应用的Bundle名称,abilityName为待启动的Ability名称,moduleName在待启动的UIAbility属于不同的Module时添加,parameters为自定义信息参数。示例中的context的获取方式请参见获取UIAbility的上下文信息。
import { common, Want } from '@kit.AbilityKit'; import { hilog } from '@kit.PerformanceAnalysisKit'; import { BusinessError } from '@kit.BasicServicesKit'; const TAG: string = '[Page_UIAbilityComponentsInteractive]'; const DOMAIN_NUMBER: number = 0xFF00; @Entry @Component struct Page_UIAbilityComponentsInteractive { private context = getContext(this) as common.UIAbilityContext; build() { Column() { //... List({ initialIndex: 0 }) { ListItem() { Row() { //... } .onClick(() => { // context为Ability对象的成员,在非Ability对象内部调用需要 // 将Context对象传递过去 let wantInfo: Want = { deviceId: '', // deviceId为空表示本设备 bundleName: 'com.samples.stagemodelabilitydevelop', moduleName: 'entry', // moduleName非必选 abilityName: 'FuncAbilityA', parameters: { // 自定义信息 info: '来自EntryAbility Page_UIAbilityComponentsInteractive页面' }, }; // context为调用方UIAbility的UIAbilityContext this.context.startAbility(wantInfo).then(() => { hilog.info(DOMAIN_NUMBER, TAG, 'startAbility success.'); }).catch((error: BusinessError) => { hilog.error(DOMAIN_NUMBER, TAG, 'startAbility failed.'); }); }) } //... } //... } //... } } -
在FuncAbility的onCreate()或者onNewWant()生命周期回调文件中接收EntryAbility传递过来的参数。
import { AbilityConstant, UIAbility, Want } from '@kit.AbilityKit'; export default class FuncAbilityA extends UIAbility { onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void { // 接收调用方UIAbility传过来的参数 let funcAbilityWant = want; let info = funcAbilityWant?.parameters?.info; } //... }说明
在被拉起的FuncAbility中,可以通过获取传递过来的want参数的parameters来获取拉起方UIAbility的PID、Bundle Name等信息。
-
在FuncAbility业务完成之后,如需要停止当前UIAbility实例,在FuncAbility中通过调用terminateSelf()方法实现。
import { common } from '@kit.AbilityKit'; import { hilog } from '@kit.PerformanceAnalysisKit'; const TAG: string = '[Page_FromStageModel]'; const DOMAIN_NUMBER: number = 0xFF00; @Entry @Component struct Page_FromStageModel { build() { Column() { //... Button('FuncAbilityB') .onClick(() => { let context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext; // UIAbilityContext // context为需要停止的UIAbility实例的AbilityContext context.terminateSelf((err) => { if (err.code) { hilog.error(DOMAIN_NUMBER, TAG, `Failed to terminate self. Code is ${err.code}, message is ${err.message}`); return; } }); }) } //... } }说明
调用terminateSelf()方法停止当前UIAbility实例时,默认会保留该实例的快照(Snapshot),即在最近任务列表中仍然能查看到该实例对应的任务。如不需要保留该实例的快照,可以在其对应UIAbility的module.json5配置文件中,将abilities标签的removeMissionAfterTerminate字段配置为true。
-
如需要关闭应用所有的UIAbility实例,可以调用ApplicationContext的killAllProcesses()方法实现关闭应用所有的进程。
启动应用内的UIAbility并获取返回结果
在一个EntryAbility启动另外一个FuncAbility时,希望在被启动的FuncAbility完成相关业务后,能将结果返回给调用方。例如在应用中将入口功能和账号登录功能分别设计为两个独立的UIAbility,在账号登录UIAbility中完成登录操作后,需要将登录的结果返回给入口UIAbility。
-
在EntryAbility中,调用startAbilityForResult()接口启动FuncAbility,异步回调中的data用于接收FuncAbility停止自身后返回给EntryAbility的信息。示例中的context的获取方式请参见获取UIAbility的上下文信息。
import { common, Want } from '@kit.AbilityKit'; import { hilog } from '@kit.PerformanceAnalysisKit'; import { promptAction } from '@kit.ArkUI'; import { BusinessError } from '@kit.BasicServicesKit'; const TAG: string = '[Page_UIAbilityComponentsInteractive]'; const DOMAIN_NUMBER: number = 0xFF00; @Entry @Component struct Page_UIAbilityComponentsInteractive { build() { Column() { //... List({ initialIndex: 0 }) { ListItem() { Row() { //... } .onClick(() => { let context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext; // UIAbilityContext const RESULT_CODE: number = 1001; let want: Want = { deviceId: '', // deviceId为空表示本设备 bundleName: 'com.samples.stagemodelabilitydevelop', moduleName: 'entry', // moduleName非必选 abilityName: 'FuncAbilityA', parameters: { // 自定义信息 info: '来自EntryAbility UIAbilityComponentsInteractive页面' } }; context.startAbilityForResult(want).then((data) => { if (data?.resultCode === RESULT_CODE) { // 解析被调用方UIAbility返回的信息 let info = data.want?.parameters?.info; hilog.info(DOMAIN_NUMBER, TAG, JSON.stringify(info) ?? ''); if (info !== null) { promptAction.showToast({ message: JSON.stringify(info) }); } } hilog.info(DOMAIN_NUMBER, TAG, JSON.stringify(data.resultCode) ?? ''); }).catch((err: BusinessError) => { hilog.error(DOMAIN_NUMBER, TAG, `Failed to start ability for result. Code is ${err.code}, message is ${err.message}`); }); }) } //... } //... } //... } } -
在FuncAbility停止自身时,需要调用terminateSelfWithResult()方法,入参abilityResult为FuncAbility需要返回给EntryAbility的信息。
import { common } from '@kit.AbilityKit'; import { hilog } from '@kit.PerformanceAnalysisKit'; const TAG: string = '[Page_FuncAbilityA]'; const DOMAIN_NUMBER: number = 0xFF00; @Entry @Component struct Page_FuncAbilityA { build() { Column() { //... List({ initialIndex: 0 }) { ListItem() { Row() { //... } .onClick(() => { let context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext; // UIAbilityContext const RESULT_CODE: number = 1001; let abilityResult: common.AbilityResult = { resultCode: RESULT_CODE, want: { bundleName: 'com.samples.stagemodelabilitydevelop', moduleName: 'entry', // moduleName非必选 abilityName: 'FuncAbilityB', parameters: { info: '来自FuncAbility Index页面' }, }, }; context.terminateSelfWithResult(abilityResult, (err) => { if (err.code) { hilog.error(DOMAIN_NUMBER, TAG, `Failed to terminate self with result. Code is ${err.code}, message is ${err.message}`); return; } }); }) } //... } //... } //... } } -
FuncAbility停止自身后,EntryAbility通过startAbilityForResult()方法回调接收被FuncAbility返回的信息,RESULT_CODE需要与前面的数值保持一致。
import { common, Want } from '@kit.AbilityKit'; import { hilog } from '@kit.PerformanceAnalysisKit'; import { promptAction } from '@kit.ArkUI'; import { BusinessError } from '@kit.BasicServicesKit'; const TAG: string = '[Page_UIAbilityComponentsInteractive]'; const DOMAIN_NUMBER: number = 0xFF00; @Entry @Component struct Page_UIAbilityComponentsInteractive { build() { Column() { //... List({ initialIndex: 0 }) { ListItem() { Row() { //... } .onClick(() => { let context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext; // UIAbilityContext const RESULT_CODE: number = 1001; let want: Want = { deviceId: '', // deviceId为空表示本设备 bundleName: 'com.samples.stagemodelabilitydevelop', moduleName: 'entry', // moduleName非必选 abilityName: 'FuncAbilityA', parameters: { // 自定义信息 info: '来自EntryAbility UIAbilityComponentsInteractive页面' } }; context.startAbilityForResult(want).then((data) => { if (data?.resultCode === RESULT_CODE) { // 解析被调用方UIAbility返回的信息 let info = data.want?.parameters?.info; hilog.info(DOMAIN_NUMBER, TAG, JSON.stringify(info) ?? ''); if (info !== null) { promptAction.showToast({ message: JSON.stringify(info) }); } } hilog.info(DOMAIN_NUMBER, TAG, JSON.stringify(data.resultCode) ?? ''); }).catch((err: BusinessError) => { hilog.error(DOMAIN_NUMBER, TAG, `Failed to start ability for result. Code is ${err.code}, message is ${err.message}`); }); }) } //... } //... } //... } }
启动UIAbility的指定页面
概述
一个UIAbility可以对应多个页面,在不同的场景下启动该UIAbility时需要展示不同的页面,例如从一个UIAbility的页面中跳转到另外一个UIAbility时,希望启动目标UIAbility的指定页面。
UIAbility的启动分为两种情况:UIAbility冷启动和UIAbility热启动。
- UIAbility冷启动:指的是UIAbility实例处于完全关闭状态下被启动,这需要完整地加载和初始化UIAbility实例的代码、资源等。
- UIAbility热启动:指的是UIAbility实例已经启动并在前台运行过,由于某些原因切换到后台,再次启动该UIAbility实例,这种情况下可以快速恢复UIAbility实例的状态。
调用方UIAbility指定启动页面
调用方UIAbility启动另外一个UIAbility时,通常需要跳转到指定的页面。例如FuncAbility包含两个页面(Index对应首页,Second对应功能A页面),此时需要在传入的want参数中配置指定的页面路径信息,可以通过want中的parameters参数增加一个自定义参数传递页面跳转信息。示例中的context的获取方式请参见获取UIAbility的上下文信息。
import { common, Want } from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { BusinessError } from '@kit.BasicServicesKit';
const TAG: string = '[Page_UIAbilityComponentsInteractive]';
const DOMAIN_NUMBER: number = 0xFF00;
@Entry
@Component
struct Page_UIAbilityComponentsInteractive {
build() {
Column() {
//...
List({ initialIndex: 0 }) {
ListItem() {
Row() {
//...
}
.onClick(() => {
let context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext; // UIAbilityContext
let want: Want = {
deviceId: '', // deviceId为空表示本设备
bundleName: 'com.samples.stagemodelabilityinteraction',
moduleName: 'entry', // moduleName非必选
abilityName: 'FuncAbility',
parameters: { // 自定义参数传递页面信息
router: 'funcA'
}
};
// context为调用方UIAbility的UIAbilityContext
context.startAbility(want).then(() => {
hilog.info(DOMAIN_NUMBER, TAG, 'Succeeded in starting ability.');
}).catch((err: BusinessError) => {
hilog.error(DOMAIN_NUMBER, TAG, `Failed to start ability. Code is ${err.code}, message is ${err.message}`);
});
})
}
//...
}
//...
}
//...
}
}
目标UIAbility冷启动
目标UIAbility冷启动时,在目标UIAbility的onCreate()生命周期回调中,接收调用方传过来的参数。然后在目标UIAbility的onWindowStageCreate()生命周期回调中,解析调用方传递过来的want参数,获取到需要加载的页面信息url,传入windowStage.loadContent()方法。
目标UIAbility热启动
在应用开发中,会遇到目标UIAbility实例之前已经启动过的场景,这时再次启动目标UIAbility时,不会重新走初始化逻辑,只会直接触发onNewWant()生命周期方法。为了实现跳转到指定页面,需要在onNewWant()中解析参数进行处理。
例如短信应用和联系人应用配合使用的场景。
- 用户先打开短信应用,短信应用的UIAbility实例启动,显示短信应用的主页。
- 用户将设备回到桌面界面,短信应用进入后台运行状态。
- 用户打开联系人应用,找到联系人张三。
- 用户点击联系人张三的短信按钮,会重新启动短信应用的UIAbility实例。
- 由于短信应用的UIAbility实例已经启动过了,此时会触发该UIAbility的onNewWant()回调,而不会再走onCreate()和onWindowStageCreate()等初始化逻辑。
开发步骤如下所示。
-
冷启动短信应用的UIAbility实例时,在onWindowStageCreate()生命周期回调中,通过调用getUIContext()接口获取UI上下文实例UIContext对象。
import { hilog } from '@kit.PerformanceAnalysisKit'; import { Want, UIAbility } from '@kit.AbilityKit'; import { window, UIContext } from '@kit.ArkUI'; const DOMAIN_NUMBER: number = 0xFF00; const TAG: string = '[EntryAbility]'; export default class EntryAbility extends UIAbility { funcAbilityWant: Want | undefined = undefined; uiContext: UIContext | undefined = undefined; // ... onWindowStageCreate(windowStage: window.WindowStage): void { // Main window is created, set main page for this ability hilog.info(DOMAIN_NUMBER, TAG, '%{public}s', 'Ability onWindowStageCreate'); let url = 'pages/Index'; if (this.funcAbilityWant?.parameters?.router && this.funcAbilityWant.parameters.router === 'funcA') { url = 'pages/Page_ColdStartUp'; } windowStage.loadContent(url, (err, data) => { if (err.code) { return; } let windowClass: window.Window; windowStage.getMainWindow((err, data) => { if (err.code) { hilog.error(DOMAIN_NUMBER, TAG, `Failed to obtain the main window. Code is ${err.code}, message is ${err.message}`); return; } windowClass = data; this.uiContext = windowClass.getUIContext(); }); hilog.info(DOMAIN_NUMBER, TAG, 'Succeeded in loading the content. Data: %{public}s', JSON.stringify(data) ?? ''); }); } } -
在短信应用UIAbility的onNewWant()回调中解析调用方传递过来的want参数,通过调用UIContext中的getRouter()方法获取Router对象,并进行指定页面的跳转。此时再次启动该短信应用的UIAbility实例时,即可跳转到该短信应用的UIAbility实例的指定页面。
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}`); }); } } } }说明
当被调用方UIAbility组件启动模式设置为multiton启动模式时,每次启动都会创建一个新的实例,那么onNewWant()回调就不会被用到。
更多推荐



所有评论(0)