HarmonyOS 应用开发之UIAbility组件启动模式

871 篇文章 15 订阅
694 篇文章 18 订阅

UIAbility的启动模式是指UIAbility实例在启动时的不同呈现状态。针对不同的业务场景,系统提供了三种启动模式:

  • singleton(单实例模式)
  • multiton(多实例模式)
  • specified(指定实例模式)

singleton启动模式

singleton启动模式为单实例模式,也是默认情况下的启动模式。

每次调用 startAbility() 方法时,如果应用进程中该类型的UIAbility实例已经存在,则复用系统中的UIAbility实例。系统中只存在唯一一个该UIAbility实例,即在最近任务列表中只存在一个该类型的UIAbility实例。

图1 单实例模式演示效果

说明
应用的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(多实例模式)。

图2 多实例模式演示效果

multiton启动模式的开发使用,在 module.json5配置文件 中的launchType字段配置为multiton即可。

{
  "module": {
    ...
    "abilities": [
      {
        "launchType": "multiton",
        ...
      }
    ]
  }
}

specified启动模式

specified启动模式为指定实例模式,针对一些特殊场景使用(例如文档应用中每次新建文档希望都能新建一个文档实例,重复打开一个已保存的文档希望打开的都是同一个文档实例)。

图3 指定实例模式演示效果

例如有两个UIAbility:EntryAbility和SpecifiedAbility,SpecifiedAbility配置为指定实例模式启动,需要从EntryAbility的页面中启动SpecifiedAbility。

  1. 在SpecifiedAbility中,将 module.json5配置文件 的launchType字段配置为specified
{
  "module": {
    ...
    "abilities": [
      {
        "launchType": "specified",
        ...
      }
    ]
  }
}
  1. 在创建UIAbility实例之前,开发者可以为该实例指定一个唯一的字符串Key,这样在调用 startAbility() 方法时,应用就可以根据指定的Key来识别响应请求的UIAbility实例。在EntryAbility中,调用 startAbility() 方法时,可以在want参数中增加一个自定义参数,例如instanceKey,以此来区分不同的UIAbility实例。
// 在启动指定实例模式的UIAbility时,给每一个UIAbility实例配置一个独立的Key标识
// 例如在文档使用场景中,可以用文档路径作为Key标识
import common from '@ohos.app.ability.common';
import hilog from '@ohos.hilog';
import Want from '@ohos.app.ability.Want';
import { BusinessError } from '@ohos.base';

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%')
  }
}
  1. 由于SpecifiedAbility的启动模式被配置为指定实例启动模式,因此在SpecifiedAbility启动之前,会先进入对应的AbilityStage的 onAcceptWant() 生命周期回调中,以获取该UIAbility实例的Key值。然后系统会自动匹配,如果存在与该UIAbility实例匹配的Key,则会启动与之绑定的UIAbility实例,并进入该UIAbility实例的 onNewWant() 回调函数;否则会创建一个新的UIAbility实例,并进入该UIAbility实例的 onCreate() 回调函数和 onWindowStageCreate() 回调函数。

示例代码中,通过实现 onAcceptWant() 生命周期回调函数,解析传入的want参数,获取自定义参数instanceKey。业务逻辑会根据这个参数返回一个字符串Key,用于标识当前UIAbility实例。如果返回的Key已经对应一个已启动的UIAbility实例,系统会将该UIAbility实例拉回前台并获焦,而不会创建新的实例。如果返回的Key没有对应已启动的UIAbility实例,则系统会创建新的UIAbility实例并启动。

import AbilityStage from '@ohos.app.ability.AbilityStage';
import type Want from '@ohos.app.ability.Want';

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 '';
  }
}

说明:

  1. 当应用的UIAbility实例已经被创建,并且配置为指定实例模式时,如果再次调用 startAbility() 方法启动该UIAbility实例,且 AbilityStage 的 onAcceptWant() 回调匹配到一个已创建的UIAbility实例,则系统会启动原来的UIAbility实例,并且不会重新创建一个新的UIAbility实例。此时,该UIAbility实例的 onNewWant() 回调会被触发,而不会触发 onCreate()onWindowStageCreate() 生命周期回调。
  2. DevEco Studio默认工程中未自动生成AbilityStage,AbilityStage文件的创建请参见AbilityStage组件容器

例如在文档应用中,可以为不同的文档实例内容绑定不同的Key值。每次新建文档时,可以传入一个新的Key值(例如可以将文件的路径作为一个Key标识),此时AbilityStage中启动UIAbility时都会创建一个新的UIAbility实例;当新建的文档保存之后,回到桌面,或者新打开一个已保存的文档,回到桌面,此时再次打开该已保存的文档,此时AbilityStage中再次启动该UIAbility时,打开的仍然是之前原来已保存的文档界面。

以如下步骤所示进行举例说明。

  1. 打开文件A,对应启动一个新的UIAbility实例,例如启动UIAbility实例1
  2. 在最近任务列表中关闭文件A的任务进程,此时UIAbility实例1被销毁,回到桌面,再次打开文件A,此时对应启动一个新的UIAbility实例,例如启动UIAbility实例2
  3. 回到桌面,打开文件B,此时对应启动一个新的UIAbility实例,例如启动UIAbility实例3
  4. 回到桌面,再次打开文件A,此时仍然启动之前的UIAbility实例2,因为系统会自动匹配UIAbility实例的Key值,如果存在与之匹配的Key,则会启动与之绑定的UIAbility实例。在此例中,之前启动的UIAbility实例2文件A绑定的Key是相同的,因此系统会拉回UIAbility实例2并让其获焦,而不会创建新的实例。

为了能让大家更好的学习鸿蒙(HarmonyOS NEXT)开发技术,这边特意整理了《鸿蒙开发学习手册》(共计890页),希望对大家有所帮助:https://qr21.cn/FV7h05

《鸿蒙开发学习手册》:

如何快速入门:https://qr21.cn/FV7h05

  1. 基本概念
  2. 构建第一个ArkTS应用
  3. ……

开发基础知识:https://qr21.cn/FV7h05

  1. 应用基础知识
  2. 配置文件
  3. 应用数据管理
  4. 应用安全管理
  5. 应用隐私保护
  6. 三方应用调用管控机制
  7. 资源分类与访问
  8. 学习ArkTS语言
  9. ……

基于ArkTS 开发:https://qr21.cn/FV7h05

  1. Ability开发
  2. UI开发
  3. 公共事件与通知
  4. 窗口管理
  5. 媒体
  6. 安全
  7. 网络与链接
  8. 电话服务
  9. 数据管理
  10. 后台任务(Background Task)管理
  11. 设备管理
  12. 设备使用信息统计
  13. DFX
  14. 国际化开发
  15. 折叠屏系列
  16. ……

鸿蒙开发面试真题(含参考答案):https://qr18.cn/F781PH

鸿蒙开发面试大盘集篇(共计319页):https://qr18.cn/F781PH

1.项目开发必备面试题
2.性能优化方向
3.架构方向
4.鸿蒙开发系统底层方向
5.鸿蒙音视频开发方向
6.鸿蒙车载开发方向
7.鸿蒙南向开发方向

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值