未验证 提交 3d737f16 编写于 作者: O openharmony_ci 提交者: Gitee

!21425 优化“启动UIAbility的指定页面 > 目标UIAbility非首次启动”的场景

Merge pull request !21425 from zyjhandsome/master
...@@ -35,8 +35,8 @@ UIAbility是系统调度的最小单元。在设备内的功能模块之间跳 ...@@ -35,8 +35,8 @@ UIAbility是系统调度的最小单元。在设备内的功能模块之间跳
let want = { let want = {
deviceId: '', // deviceId为空表示本设备 deviceId: '', // deviceId为空表示本设备
bundleName: 'com.example.myapplication', bundleName: 'com.example.myapplication',
abilityName: 'FuncAbility',
moduleName: 'func', // moduleName非必选 moduleName: 'func', // moduleName非必选
abilityName: 'FuncAbility',
parameters: { // 自定义信息 parameters: { // 自定义信息
info: '来自EntryAbility Index页面', info: '来自EntryAbility Index页面',
}, },
...@@ -100,8 +100,8 @@ UIAbility是系统调度的最小单元。在设备内的功能模块之间跳 ...@@ -100,8 +100,8 @@ UIAbility是系统调度的最小单元。在设备内的功能模块之间跳
let want = { let want = {
deviceId: '', // deviceId为空表示本设备 deviceId: '', // deviceId为空表示本设备
bundleName: 'com.example.myapplication', bundleName: 'com.example.myapplication',
abilityName: 'FuncAbility',
moduleName: 'func', // moduleName非必选 moduleName: 'func', // moduleName非必选
abilityName: 'FuncAbility',
parameters: { // 自定义信息 parameters: { // 自定义信息
info: '来自EntryAbility Index页面', info: '来自EntryAbility Index页面',
}, },
...@@ -123,8 +123,8 @@ UIAbility是系统调度的最小单元。在设备内的功能模块之间跳 ...@@ -123,8 +123,8 @@ UIAbility是系统调度的最小单元。在设备内的功能模块之间跳
resultCode: RESULT_CODE, resultCode: RESULT_CODE,
want: { want: {
bundleName: 'com.example.myapplication', bundleName: 'com.example.myapplication',
moduleName: 'func', // moduleName非必选
abilityName: 'FuncAbility', abilityName: 'FuncAbility',
moduleName: 'func',
parameters: { parameters: {
info: '来自FuncAbility Index页面', info: '来自FuncAbility Index页面',
}, },
...@@ -296,9 +296,9 @@ UIAbility是系统调度的最小单元。在设备内的功能模块之间跳 ...@@ -296,9 +296,9 @@ UIAbility是系统调度的最小单元。在设备内的功能模块之间跳
let abilityResult = { let abilityResult = {
resultCode: RESULT_CODE, resultCode: RESULT_CODE,
want: { want: {
bundleName: 'com.example.myapplication', bundleName: 'com.example.funcapplication',
moduleName: 'entry', // moduleName非必选
abilityName: 'EntryAbility', abilityName: 'EntryAbility',
moduleName: 'entry',
parameters: { parameters: {
payResult: 'OKay', payResult: 'OKay',
}, },
...@@ -366,8 +366,8 @@ let context = ...; // UIAbilityContext ...@@ -366,8 +366,8 @@ let context = ...; // UIAbilityContext
let want = { let want = {
deviceId: '', // deviceId为空表示本设备 deviceId: '', // deviceId为空表示本设备
bundleName: 'com.example.myapplication', bundleName: 'com.example.myapplication',
abilityName: 'FuncAbility',
moduleName: 'func', // moduleName非必选 moduleName: 'func', // moduleName非必选
abilityName: 'FuncAbility',
parameters: { // 自定义信息 parameters: { // 自定义信息
info: '来自EntryAbility Index页面', info: '来自EntryAbility Index页面',
}, },
...@@ -400,9 +400,9 @@ context.startAbility(want, options).then(() => { ...@@ -400,9 +400,9 @@ context.startAbility(want, options).then(() => {
let context = ...; // UIAbilityContext let context = ...; // UIAbilityContext
let want = { let want = {
deviceId: '', // deviceId为空表示本设备 deviceId: '', // deviceId为空表示本设备
bundleName: 'com.example.myapplication', bundleName: 'com.example.funcapplication',
abilityName: 'FuncAbility', moduleName: 'entry', // moduleName非必选
moduleName: 'func', // moduleName非必选 abilityName: 'EntryAbility',
parameters: { // 自定义参数传递页面信息 parameters: { // 自定义参数传递页面信息
router: 'funcA', router: 'funcA',
}, },
...@@ -422,25 +422,25 @@ context.startAbility(want).then(() => { ...@@ -422,25 +422,25 @@ context.startAbility(want).then(() => {
```ts ```ts
import UIAbility from '@ohos.app.ability.UIAbility' import AbilityConstant from '@ohos.app.ability.AbilityConstant';
import Window from '@ohos.window' import UIAbility from '@ohos.app.ability.UIAbility';
import Want from '@ohos.app.ability.Want';
import window from '@ohos.window';
export default class FuncAbility extends UIAbility { export default class FuncAbility extends UIAbility {
funcAbilityWant; funcAbilityWant: Want;
onCreate(want, launchParam) { onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) {
// 接收调用方UIAbility传过来的参数 // 接收调用方UIAbility传过来的参数
this.funcAbilityWant = want; this.funcAbilityWant = want;
} }
onWindowStageCreate(windowStage: Window.WindowStage) { onWindowStageCreate(windowStage: window.WindowStage) {
// Main window is created, set main page for this ability // Main window is created, set main page for this ability
let url = 'pages/Index'; let url = 'pages/Index';
if (this.funcAbilityWant?.parameters?.router) { if (this.funcAbilityWant?.parameters?.router && this.funcAbilityWant.parameters.router === 'funcA') {
if (this.funcAbilityWant.parameters.router === 'funA') {
url = 'pages/Second'; url = 'pages/Second';
} }
}
windowStage.loadContent(url, (err, data) => { windowStage.loadContent(url, (err, data) => {
... ...
}); });
...@@ -448,55 +448,95 @@ export default class FuncAbility extends UIAbility { ...@@ -448,55 +448,95 @@ export default class FuncAbility extends UIAbility {
} }
``` ```
### 目标UIAbility非首次启动 ### 目标UIAbility非首次启动
经常还会遇到一类场景,当应用A已经启动且处于主页面时,回到桌面,打开应用B,并从应用B再次启动应用A,且需要跳转到应用A的指定页面。例如联系人应用和短信应用配合使用的场景。打开短信应用主页,回到桌面,此时短信应用处于已打开状态且当前处于短信应用的主页。再打开联系人应用主页,进入联系人用户A查看详情,点击短信图标,准备给用户A发送短信,此时会再次拉起短信应用且当前处于短信应用的发送页面。 在应用开发中,会遇到目标UIAbility实例之前已经启动过的场景,这时再次启动目标UIAbility时,不会重新走初始化逻辑,只会直接触发`onNewWant()`生命周期方法。为了实现跳转到指定页面,需要在`onNewWant()`中解析要参数进行处理。
![uiability_not_first_started](figures/uiability_not_first_started.png) 例如短信应用和联系人应用配合使用的场景。
1. 用户先打开短信应用,短信应用的UIAbility实例启动,显示短信应用的主页。
2. 用户将设备回到桌面界面,短信应用进入后台运行状态。
3. 用户打开联系人应用,找到联系人张三。
4. 用户点击联系人张三的短信按钮,会重新启动短信应用的UIAbility实例。
5. 由于短信应用的UIAbility实例已经启动过了,此时会触发该UIAbility的`onNewWant()`回调,而不会再走`onCreate()``onWindowStageCreate()`等初始化逻辑。
```mermaid
sequenceDiagram
Participant U as 用户
Participant S as 短信应用
Participant C as 联系人应用
U->>S: 打开短信应用
S-->>U: 显示短信应用主页
U->>S: 将设备回到桌面界面
S->>S: 短信应用进入后台
U->>C: 打开联系人应用
C-->>U: 显示联系人应用界面
U->>C: 点击联系人张三的短信按钮
C->>S: 构造Want启动短信应用
S-->>U: 显示给张三发短信的页面
```
针对以上场景,即当应用A的UIAbility实例已创建,并且处于该UIAbility实例对应的主页面中,此时,从应用B中需要再次启动应用A的该UIAbility,并且需要跳转到不同的页面,这种情况下要如何实现呢? 开发步骤如下所示。
1. 在目标UIAbility中,默认加载的是Index页面。由于当前UIAbility实例之前已经创建完成,此时会进入UIAbility的`onNewWant()`回调中且不会进入`onCreate()``onWindowStageCreate()`生命周期回调,在onNewWant()回调中解析调用方传递过来的want参数,并挂在到全局变量globalThis中,以便于后续在页面中获取 1. 首次启动短信应用的UIAbility实例时,在`onWindowStageCreate()`生命周期回调中,通过调用[`getUIContext()`](../reference/apis/js-apis-window.md#getuicontext10)接口获取UI上下文实例[`UIContext`](../reference/apis/js-apis-arkui-UIContext.md)对象
```ts ```ts
import UIAbility from '@ohos.app.ability.UIAbility' import AbilityConstant from '@ohos.app.ability.AbilityConstant';
import UIAbility from '@ohos.app.ability.UIAbility';
import Want from '@ohos.app.ability.Want';
import window from '@ohos.window';
export default class FuncAbility extends UIAbility { import { Router, UIContext } from '@ohos.arkui.UIContext';
onNewWant(want, launchParam) {
// 接收调用方UIAbility传过来的参数 export default class EntryAbility extends UIAbility {
globalThis.funcAbilityWant = want; funcAbilityWant: Want;
uiContext: UIContext;
...
onWindowStageCreate(windowStage: window.WindowStage) {
// Main window is created, set main page for this ability
... ...
let windowClass: window.Window;
windowStage.getMainWindow((err, data) => {
if (err.code) {
console.error(`Failed to obtain the main window. Code is ${err.code}, message is ${err.message}`);
return;
}
windowClass = data;
this.uiContext = windowClass.getUIContext();
})
} }
} }
``` ```
2.FuncAbility中,此时需要在Index页面中通过页面路由Router模块实现指定页面的跳转,由于此时FuncAbility对应的Index页面是处于激活状态,不会重新变量声明以及进入`aboutToAppear()`生命周期回调中。因此可以在Index页面的`onPageShow()`生命周期回调中实现页面路由跳转的功能 2.短信应用UIAbility的`onNewWant()`回调中解析调用方传递过来的want参数,通过调用UIContext中的[`getRouter()`](../reference/apis/js-apis-arkui-UIContext.md#getrouter)方法获取[`Router`](../reference/apis/js-apis-arkui-UIContext.md#router)对象,并进行指定页面的跳转。此时再次启动该短信应用的UIAbility实例时,即可跳转到该短信应用的UIAbility实例的指定页面
```ts ```ts
import router from '@ohos.router'; export default class EntryAbility extends UIAbility {
funcAbilityWant: Want;
@Entry uiContext: UIContext;
@Component
struct Index { onNewWant(want: Want, launchParams: AbilityConstant.LaunchParam) {
onPageShow() { if (want?.parameters?.router && want.parameters.router === 'funcA') {
let funcAbilityWant = globalThis.funcAbilityWant; let funcAUrl = 'pages/Second';
let url2 = funcAbilityWant?.parameters?.router; let router: Router = this.uiContext.getRouter();
if (url2 && url2 === 'funcA') { router.pushUrl({
router.replaceUrl({ url: funcAUrl
url: 'pages/Second', }).catch((err) => {
console.error(`Failed to push url. Code is ${err.code}, message is ${err.message}`);
}) })
} }
} }
// 页面展示
build() {
... ...
} }
}
``` ```
> **说明:** > **说明:**
>
> 当被调用方[UIAbility组件启动模式](uiability-launch-type.md)设置为multiton启动模式时,每次启动都会创建一个新的实例,那么[onNewWant()](../reference/apis/js-apis-app-ability-uiAbility.md#abilityonnewwant)回调就不会被用到。 > 当被调用方[UIAbility组件启动模式](uiability-launch-type.md)设置为multiton启动模式时,每次启动都会创建一个新的实例,那么[onNewWant()](../reference/apis/js-apis-app-ability-uiAbility.md#abilityonnewwant)回调就不会被用到。
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册