关于harmonyos:鸿蒙学习笔记Stage模型UIAbility

25次阅读

共计 17481 个字符,预计需要花费 44 分钟才能阅读完成。

「鸿蒙学习笔记」Stage 模型 –UIAbility

概述

UIAbility 组件是一种蕴含 UI 界面的利用组件,次要用于和用户交互。

UIAbility 组件是系统调度的根本单元,为利用提供绘制界面的窗口;一个 UIAbility 组件中能够通过多个页面来实现一个功能模块。每一个 UIAbility 组件实例,都对应于一个最近工作列表中的工作。

配置

为使利用可能失常应用 UIAbility,须要在 module.json5 配置文件的 abilities 标签 中申明 UIAbility 的名称、入口、标签等相干信息。

{
  "module": {
    // ...
    "abilities": [
      {
        "name": "EntryAbility", // UIAbility 组件的名称
        "srcEntrance": "./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 组件启动页面背景色彩资源文件的索引
        // ...
      }
    ]
  }
}

生命周期

启动模式

针对不同的业务场景,零碎提供了三种启动模式:

  • singleton(单实例模式)
  • standard(规范实例模式)
  • specified(指定实例模式)

singleton(单实例模式)

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

每次调用 startAbility() 办法时,如果利用过程中该类型的 UIAbility 实例曾经存在,则复用零碎中的 UIAbility 实例。零碎中只存在惟一一个该 UIAbility 实例,即在最近工作列表中只存在一个该类型的 UIAbility 实例。

利用的 UIAbility 实例已创立,该 UIAbility 配置为单实例模式,再次调用 startAbility() 办法启动该 UIAbility 实例,此时只会进入该 UIAbility 的 onNewWant() 回调,不会进入其 onCreate() 和 onWindowStageCreate() 生命周期回调。

在 module.json5 配置文件中的 ”launchType” 字段配置为 ”singleton” 即可。

{
  "module": {
    // ...
    "abilities": [
      {
        "launchType": "singleton",
        // ...
      }
    ]
  }
}

standard(规范实例模式)

standard 启动模式为规范实例模式,每次调用 startAbility() 办法时,都会在利用过程中创立一个新的该类型 UIAbility 实例。即在最近工作列表中能够看到有多个该类型的 UIAbility 实例。这种状况下能够将 UIAbility 配置为 standard(规范实例模式)。

在 module.json5 配置文件中的 ”launchType” 字段配置为 ”standard” 即可。

{
  "module": {
    // ...
    "abilities": [
      {
        "launchType": "standard",
        // ...
      }
    ]
  }
}

specified(指定实例模式)

specified 启动模式为指定实例模式,针对一些非凡场景应用(例如文档利用中每次新建文档心愿都能新建一个文档实例,反复关上一个已保留的文档心愿关上的都是同一个文档实例)。

在 UIAbility 实例创立之前,容许开发者为该实例创立一个惟一的字符串 Key,创立的 UIAbility 实例绑定 Key 之后,后续每次调用 startAbility() 办法时,都会询问利用应用哪个 Key 对应的 UIAbility 实例来响应 startAbility() 申请。运行时由 UIAbility 外部业务决定是否创立多实例,如果匹配有该 UIAbility 实例的 Key,则间接拉起与之绑定的 UIAbility 实例,否则创立一个新的 UIAbility 实例。

利用的 UIAbility 实例已创立,该 UIAbility 配置为指定实例模式,再次调用 startAbility() 办法启动该 UIAbility 实例,且 AbilityStage 的 onAcceptWant() 回调匹配到一个已创立的 UIAbility 实例。此时,再次启动该 UIAbility 时,只会进入该 UIAbility 的 onNewWant() 回调,不会进入其 onCreate() 和 onWindowStageCreate() 生命周期回调。

例如有两个 UIAbility:EntryAbility 和 FuncAbility,FuncAbility 配置为 specified 启动模式,须要从 EntryAbility 的页面中启动 FuncAbility。

  1. 在 module.json5 配置文件中的 ”launchType” 字段配置为 ”specified” 即可。

    {
      "module": {
     // ...
     "abilities": [
       {
         "launchType": "specified",
         // ...
       }
     ]
      }
    }
  2. 在 EntryAbility 中,调用 startAbility() 办法时,在 want 参数中,减少一个自定义参数来区别 UIAbility 实例,例如减少一个 ”instanceKey” 自定义参数。

    // 在启动指定实例模式的 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) => {// ...})
  3. 因为 FuncAbility 的启动模式配置为了指定实例启动模式,在 FuncAbility 启动之前,会先进入其对应的 AbilityStage 的 onAcceptWant() 生命周期回调中,解析传入的 want 参数,获取 ”instanceKey” 自定义参数。依据业务须要通过 AbilityStage 的 onAcceptWant() 生命周期回调返回一个字符串 Key 标识。如果返回的 Key 对应一个已启动的 UIAbility,则会将之前的 UIAbility 拉回前台并获焦,而不创立新的实例,否则创立新的实例并启动。

    import AbilityStage from '@ohos.app.ability.AbilityStage';
    
    export default class MyAbilityStage extends AbilityStage {onAcceptWant(want): string {
         // 在被调用方的 AbilityStage 中,针对启动模式为 specified 的 UIAbility 返回一个 UIAbility 实例对应的一个 Key 值
         // 以后示例指的是 module1 Module 的 FuncAbility
         if (want.abilityName === 'FuncAbility') {
             // 返回的字符串 Key 标识为自定义拼接的字符串内容
             return `ControlModule_EntryAbilityInstance_${want.parameters.instanceKey}`;
         }
    
         return '';
     }
    }

例如在文档利用中,能够对不同的文档实例内容绑定不同的 Key 值。当每次新建文档的时候,能够传入不同的新 Key 值(如能够将文件的门路作为一个 Key 标识),此时 AbilityStage 中启动 UIAbility 时都会创立一个新的 UIAbility 实例;当新建的文档保留之后,回到桌面,或者新关上一个已保留的文档,回到桌面,此时再次关上该已保留的文档,此时 AbilityStage 中再次启动该 UIAbility 时,关上的依然是之前原来已保留的文档界面。

根本用法

指定 UIAbility 的启动页面

利用中的 UIAbility 在启动过程中,须要指定启动页面,否则利用启动后会因为没有默认加载页面而导致白屏。能够在 UIAbility 的 onWindowStageCreate() 生命周期回调中,通过 WindowStage 对象的 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 的上下文信息

UIAbility 类领有本身的上下文信息,该信息为 UIAbilityContext 类的实例,UIAbilityContext 类领有 abilityInfo、currentHapModuleInfo 等属性。通过 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() {// ...}
    }

UI 数据同步

基于 HarmonyOS 的利用模型,能够通过以下两种形式来实现 UIAbility 组件与 UI 之间的数据同步。

  • EventHub:基于公布订阅模式来实现,事件须要先订阅后公布,订阅者收到音讯后进行解决。
  • globalThis:ArkTS 引擎实例外部的一个全局对象,在 ArkTS 引擎实例外部都能拜访。

应用 EventHub 进行数据通信

EventHub 提供了 UIAbility 组件 /ExtensionAbility 组件级别的事件机制,以 UIAbility 组件 /ExtensionAbility 组件为核心提供了订阅、勾销订阅和触发事件的数据通信能力。接口阐明请参见 EventHub。

在应用 EventHub 之前,首先须要获取 EventHub 对象。基类 Context 提供了 EventHub 对象,本章节以应用 EventHub 实现 UIAbility 与 UI 之间的数据通信为例进行阐明。

  1. 在 UIAbility 中调用 eventHub.on() 办法注册一个自定义事件“event1”,eventHub.on() 有如下两种调用形式,应用其中一种即可。
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));
        });
    }
}
  1. 在 UI 界面中通过 eventHub.emit() 办法触发该事件,在触发事件的同时,依据须要传入参数信息。

    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() {// ...}
    }
  2. 在 UIAbility 的注册事件回调中能够失去对应的触发事件后果,运行日志后果如下所示。

    []
    
    [1]
    
    [2,'test']
  3. 在自定义事件“event1”应用实现后,能够依据须要调用 eventHub.off() 办法勾销该事件的订阅。

    // context 为 UIAbility 实例的 AbilityContext
    this.context.eventHub.off('event1');

应用 globalThis 进行数据同步

globalThis 是 ArkTS 引擎实例外部的一个全局对象,引擎外部的 UIAbility/ExtensionAbility/Page 都能够应用,因而能够应用 globalThis 全局对象进行数据同步。

从如下三个场景和一个留神点来介绍 globalThis 的应用:

  • UIAbility 和 Page 之间应用 globalThis
  • UIAbility 和 UIAbility 之间应用 globalThis
  • UIAbility 和 ExtensionAbility 之间应用 globalThis
  • globalThis 应用的注意事项
UIAbility 和 Page 之间应用 globalThis

globalThis 为 ArkTS 引擎实例下的全局对象,能够通过 globalThis 绑定属性 / 办法来进行 UIAbility 组件与 UI 的数据同步。例如在 UIAbility 组件中绑定 want 参数,即可在 UIAbility 对应的 UI 界面上应用 want 参数信息。

  1. 调用 startAbility() 办法启动一个 UIAbility 实例时,被启动的 UIAbility 创立实现后会进入 onCreate() 生命周期回调,且在 onCreate() 生命周期回调中可能承受到传递过去的 want 参数,能够将 want 参数绑定到 globalThis 上。

    import UIAbility from '@ohos.app.ability.UIAbility'
    
    export default class EntryAbility extends UIAbility {onCreate(want, launch) {
         globalThis.entryAbilityWant = want;
         // ...
     }
    
     // ...
    }
  2. 在 UI 界面中即可通过 globalThis 获取到 want 参数信息。

    let entryAbilityWant;
    
    @Entry
    @Component
    struct Index {aboutToAppear() {entryAbilityWant = globalThis.entryAbilityWant;}
    
      // 页面展现
      build() {// ...}
    }
UIAbility 和 UIAbility 之间应用 globalThis

同一个利用中 UIAbility 和 UIAbility 之间的数据传递,能够通过将数据绑定到全局变量 globalThis 上进行同步,如在 AbilityA 中将数据保留在 globalThis,而后跳转到 AbilityB 中获得该数据:

  1. AbilityA 中保留数据一个字符串数据并挂载到 globalThis 上。

    import UIAbility from '@ohos.app.ability.UIAbility'
    
    export default class AbilityA extends UIAbility {onCreate(want, launch) {
         globalThis.entryAbilityStr = 'AbilityA'; // AbilityA 寄存字符串“AbilityA”到 globalThis
         // ...
     }
    }
  2. AbilityB 中获取对应的数据。

    import UIAbility from '@ohos.app.ability.UIAbility'
    
    export default class AbilityB extends UIAbility {onCreate(want, launch) {
         // AbilityB 从 globalThis 读取 name 并输入
         console.info('name from entryAbilityStr:' + globalThis.entryAbilityStr);
         // ...
     }
    }
UIAbility 和 ExtensionAbility 之间应用 globalThis

同一个利用中 UIAbility 和 ExtensionAbility 之间的数据传递,也能够通过将数据绑定到全局变量 globalThis 上进行同步,如在 AbilityA 中保留数据,在 ServiceExtensionAbility 中获取数据。

  1. AbilityA 中保留数据一个字符串数据并挂载到 globalThis 上。

    import UIAbility from '@ohos.app.ability.UIAbility'
    
    export default class AbilityA extends UIAbility {onCreate(want, launch) {
         // AbilityA 寄存字符串“AbilityA”到 globalThis
         globalThis.entryAbilityStr = 'AbilityA';
         // ...
     }
    }
  2. ExtensionAbility 中获取数据。

    import Extension from '@ohos.app.ability.ServiceExtensionAbility'
    
    export default class ServiceExtAbility extends Extension {onCreate(want) {
         // ServiceExtAbility 从 globalThis 读取 name 并输入
         console.info('name from entryAbilityStr:' + globalThis.entryAbilityStr);
         // ...
     }
    }
globalThis 应用的注意事项

  • Stage 模型下过程内的 UIAbility 组件共享 ArkTS 引擎实例,应用 globalThis 时须要防止寄存雷同名称的对象。例如 AbilityA 和 AbilityB 能够应用 globalThis 共享数据,在寄存雷同名称的对象时,先寄存的对象会被后寄存的对象笼罩。
  • 对于绑定在 globalThis 上的对象,其生命周期与 ArkTS 虚拟机实例雷同,倡议在应用实现之后将其赋值为 null,以缩小对利用内存的占用。

组件间交互(设施内)

UIAbility 是系统调度的最小单元。在设施内的功能模块之间跳转时,会波及到启动特定的 UIAbility,该 UIAbility 能够是利用内的其余 UIAbility,也能够是其余利用的 UIAbility(例如启动三方领取 UIAbility)。

  • 启动利用内的 UIAbility
  • 启动利用内的 UIAbility 并获取返回后果
  • 启动其余利用的 UIAbility
  • 启动其余利用的 UIAbility 并获取返回后果
  • 启动 UIAbility 的指定页面
  • 通过 Call 调用实现 UIAbility 交互(仅对系统利用凋谢)

启动利用内的 UIAbility

当一个利用内蕴含多个 UIAbility 时,存在利用内启动 UIAbility 的场景。例如在领取利用中从入口 UIAbility 启动收付款 UIAbility。

假如利用中有两个 UIAbility:EntryAbility 和 FuncAbility(能够在利用的一个 Module 中,也能够在的不同 Module 中),须要从 EntryAbility 的页面中启动 FuncAbility。

  1. 在 EntryAbility 中,通过调用 startAbility() 办法启动 UIAbility,want 为 UIAbility 实例启动的入口参数,其中 bundleName 为待启动利用的 Bundle 名称,abilityName 为待启动的 UIAbility 名称,moduleName 在待启动的 UIAbility 属于不同的 Module 时增加,parameters 为自定义信息参数。

    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) => {// ...})
  2. 在 FuncAbility 的生命周期回调文件中接管 EntryAbility 传递过去的参数。

    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;
         // ...
     }
    }
  3. 在 FuncAbility 业务实现之后,如须要进行以后 UIAbility 实例,在 FuncAbility 中通过调用 terminateSelf() 办法实现。

    // context 为须要进行的 UIAbility 实例的 AbilityContext
    this.context.terminateSelf((err) => {// ...});

启动利用内的 UIAbility 并获取返回后果

在一个 EntryAbility 启动另外一个 FuncAbility 时,心愿在被启动的 FuncAbility 实现相干业务后,能将后果返回给调用方。例如在利用中将入口性能和帐号登录性能别离设计为两个独立的 UIAbility,在帐号登录 UIAbility 中实现登录操作后,须要将登录的后果返回给入口 UIAbility。

  1. 在 EntryAbility 中,调用 startAbilityForResult() 接口启动 FuncAbility,异步回调中的 data 用于接管 FuncAbility 进行本身后返回给 EntryAbility 的信息。

    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) => {// ...})
  2. 在 FuncAbility 进行本身时,须要调用 terminateSelfWithResult() 办法,入参 abilityResult 为 FuncAbility 须要返回给 EntryAbility 的信息。

    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) => {// ...});
  3. FuncAbility 进行本身后,EntryAbility 通过 startAbilityForResult() 办法回调接管被 FuncAbility 返回的信息,RESULT_CODE 须要与后面的数值保持一致。

    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 启动。零碎会依据调用方的 want 参数来辨认和启动匹配到的利用 UIAbility。

启动 UIAbility 有显式 Want 启动和隐式 Want 启动两种形式。

  • 显式 Want 启动:启动一个确定利用的 UIAbility,在 want 参数中须要设置该利用 bundleName 和 abilityName,当须要拉起某个明确的 UIAbility 时,通常应用显式 Want 启动形式。
  • 隐式 Want 启动:依据匹配条件由用户抉择启动哪一个 UIAbility,即不明确指出要启动哪一个 UIAbility(abilityName 参数未设置),在调用 startAbility() 办法时,其入参 want 中指定了一系列的 entities 字段(示意指标 UIAbility 额定的类别信息,如浏览器、视频播放器)和 actions 字段(示意要执行的通用操作,如查看、分享、利用详情等)等参数信息,而后由零碎去剖析 want,并帮忙找到适合的 UIAbility 来启动。当须要拉起其余利用的 UIAbility 时,开发者通常不晓得用户设施中利用的装置状况,也无奈确定指标利用的 bundleName 和 abilityName,通常应用隐式 Want 启动形式。

隐式 Want 启动其余利用的 UIAbility:

  1. 将多个待匹配的文档利用装置到设施,在其对应 UIAbility 的 module.json5 配置文件中,配置 skills 的 entities 字段和 actions 字段。

    {
      "module": {
     "abilities": [
       {
         // ...
         "skills": [
           {
             "entities": [
               // ...
               "entity.system.default"
             ],
             "actions": [
               // ...
               "ohos.want.action.viewData"
             ]
           }
         ]
       }
     ]
      }
    }
  2. 在调用方 want 参数中的 entities 和 action 须要被蕴含在待匹配 UIAbility 的 skills 配置的 entities 和 actions 中。零碎匹配到合乎 entities 和 actions 参数条件的 UIAbility 后,会弹出抉择框展现匹配到的 UIAbility 实例列表供用户抉择应用。

    let wantInfo = {
     deviceId: '', // deviceId 为空示意本设施
     // uncomment line below if wish to implicitly query only in the specific bundle.
     // bundleName: 'com.example.myapplication',
     action: 'ohos.want.action.viewData',
     // entities can be omitted.
     entities: ['entity.system.default'],
    }
    
    // context 为调用方 UIAbility 的 AbilityContext
    this.context.startAbility(wantInfo).then(() => {// ...}).catch((err) => {// ...})

  3. 在文档利用应用实现之后,如须要进行以后 UIAbility 实例,通过调用 terminateSelf() 办法实现。

    // context 为须要进行的 UIAbility 实例的 AbilityContext
    this.context.terminateSelf((err) => {// ...});

启动其余利用的 UIAbility 并获取返回后果

当应用隐式 Want 启动其余利用的 UIAbility 并心愿获取返回后果时,调用方须要应用 startAbilityForResult() 办法启动指标 UIAbility。例如主利用中须要启动三方领取并获取领取后果。

  1. 在领取利用对应 UIAbility 的 module.json5 配置文件中,配置 skills 的 entities 字段和 actions 字段。

    {
      "module": {
     "abilities": [
       {
         // ...
         "skills": [
           {
             "entities": [
               // ...
               "entity.system.default"
             ],
             "actions": [
               // ...
               "ohos.want.action.editData"
             ]
           }
         ]
       }
     ]
      }
    }
  2. 调用方应用 startAbilityForResult() 办法启动领取利用的 UIAbility,在调用方 want 参数中的 entities 和 action 须要被蕴含在待匹配 UIAbility 的 skills 配置的 entities 和 actions 中。异步回调中的 data 用于后续接管领取 UIAbility 进行本身后返回给调用方的信息。零碎匹配到合乎 entities 和 actions 参数条件的 UIAbility 后,会弹出抉择框展现匹配到的 UIAbility 实例列表供用户抉择应用。

    let wantInfo = {
     deviceId: '', // deviceId 为空示意本设施
     // uncomment line below if wish to implicitly query only in the specific bundle.
     // bundleName: 'com.example.myapplication',
     action: 'ohos.want.action.editData',
     // entities can be omitted.
     entities: ['entity.system.default'],
    }
    
    // context 为调用方 UIAbility 的 AbilityContext
    this.context.startAbilityForResult(wantInfo).then((data) => {// ...}).catch((err) => {// ...})
  3. 在领取 UIAbility 实现领取之后,须要调用 terminateSelfWithResult() 办法实现进行本身,并将 abilityResult 参数信息返回给调用方。

    const RESULT_CODE: number = 1001;
    let abilityResult = {
     resultCode: RESULT_CODE,
     want: {
         bundleName: 'com.example.myapplication',
         abilityName: 'EntryAbility',
         moduleName: 'entry',
         parameters: {payResult: 'OKay',},
     },
    }
    // context 为被调用方 UIAbility 的 AbilityContext
    this.context.terminateSelfWithResult(abilityResult, (err) => {// ...});
  4. 在调用方 startAbilityForResult() 办法回调中接管领取利用返回的信息,RESULT_CODE 须要与后面 terminateSelfWithResult() 返回的数值保持一致。

    const RESULT_CODE: number = 1001;
    
    let want = {// Want 参数信息};
    
    // context 为调用方 UIAbility 的 AbilityContext
    this.context.startAbilityForResult(want).then((data) => {if (data?.resultCode === RESULT_CODE) {
         // 解析被调用方 UIAbility 返回的信息
         let payResult = data.want?.parameters?.payResult;
         // ...
     }
    }).catch((err) => {// ...})

启动 UIAbility 的指定页面

一个 UIAbility 能够对应多个页面,在不同的场景下启动该 UIAbility 时须要展现不同的页面,例如从一个 UIAbility 的页面中跳转到另外一个 UIAbility 时,心愿启动指标 UIAbility 的指定页面。

调用方 UIAbility 指定启动页面

调用方 UIAbility 启动另外一个 UIAbility 时,通常须要跳转到指定的页面。例如 FuncAbility 蕴含两个页面(Index 对应首页,Second 对应性能 A 页面),此时须要在传入的 want 参数中配置指定的页面门路信息,能够通过 want 中的 parameters 参数减少一个自定义参数传递页面跳转信息。

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 首次启动

指标 UIAbility 首次启动时,在指标 UIAbility 的 onWindowStageCreate() 生命周期回调中,解析 EntryAbility 传递过去的 want 参数,获取到须要加载的页面信息 url,传入 windowStage.loadContent() 办法。

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 === 'funA') {url = 'pages/Second';}
        }
        windowStage.loadContent(url, (err, data) => {// ...});
    }
}
指标 UIAbility 非首次启动

常常还会遇到一类场景,当利用 A 曾经启动且处于主页面时,回到桌面,关上利用 B,并从利用 B 再次启动利用 A,且须要跳转到利用 A 的指定页面。例如联系人利用和短信利用配合应用的场景。关上短信利用主页,回到桌面,此时短信利用处于已关上状态且以后处于短信利用的主页。再关上联系人利用主页,进入联系人用户 A 查看详情,点击短信图标,筹备给用户 A 发送短信,此时会再次拉起短信利用且以后处于短信利用的发送页面。

针对以上场景,即当利用 A 的 UIAbility 实例已创立,并且处于该 UIAbility 实例对应的主页面中,此时,从利用 B 中须要再次启动利用 A 的该 UIAbility,并且须要跳转到不同的页面,这种状况下要如何实现呢?

  1. 在指标 UIAbility 中,默认加载的是 Index 页面。因为以后 UIAbility 实例之前曾经创立实现,此时会进入 UIAbility 的 onNewWant() 回调中且不会进入 onCreate() 和 onWindowStageCreate() 生命周期回调,在 onNewWant() 回调中解析调用方传递过去的 want 参数,并挂在到全局变量 globalThis 中,以便于后续在页面中获取。

    import UIAbility from '@ohos.app.ability.UIAbility'
    
    export default class FuncAbility extends UIAbility {onNewWant(want, launchParam) {
         // 接管调用方 UIAbility 传过来的参数
         globalThis.funcAbilityWant = want;
         // ...
     }
    }
  2. 在 FuncAbility 中,此时须要在 Index 页面中通过页面路由 Router 模块实现指定页面的跳转,因为此时 FuncAbility 对应的 Index 页面是处于激活状态,不会从新变量申明以及进入 aboutToAppear() 生命周期回调中。因而能够在 Index 页面的 onPageShow() 生命周期回调中实现页面路由跳转的性能。

    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 的启动模式设置为 standard 启动模式时,每次启动都会创立一个新的实例,那么 onNewWant() 回调就不会被用到。

通过 Call 调用实现 UIAbility 交互(仅对系统利用凋谢)

Call 调用是 UIAbility 能力的扩大,它为 UIAbility 提供一种可能被内部调用并与内部进行通信的能力。Call 调用反对前台与后盾两种启动形式,使 UIAbility 既能被拉起到前台展现 UI,也能够在后盾被创立并运行。Call 调用在调用方与被调用方间建设了 IPC 通信,因而利用开发者可通过 Call 调用实现不同 UIAbility 之间的数据共享。

Call 调用的外围接口是 startAbilityByCall 办法,与 startAbility 接口的不同之处在于:

  • startAbilityByCall 反对前台与后盾两种启动形式,而 startAbility 仅反对前台启动。
  • 调用方可应用 startAbilityByCall 所返回的 Caller 对象与被调用方进行通信,而 startAbilty 不具备通信能力。

Call 调用的应用场景次要包含:

  • 须要与被启动的 UIAbility 进行通信。
  • 心愿被启动的 UIAbility 在后盾运行。

参考

  • https://developer.harmonyos.com/cn/docs/documentation/doc-gui…

正文完
 0