鸿蒙 Stage模型-应用组件-配置、UIAbility

news/2024/7/20 11:11:21 标签: harmonyos, 华为

前提:基于官网3.1/4.0文档。参考官网文档
基于Android开发体系来进行比较和思考。(或有偏颇,自行斟酌)

一、概念

在这里插入图片描述
可以看到分为运行期、编译器,主要关注UIAbility(类似Activity,UI相关)、ExtensionAbility(其他非UI相关)。
另外AbilityState暂时不确定是类似Android 中的Application。

为什么会单独有个Stage模型?
其实就是整体架构,只不过为了区分另外一个```Feature模型``,后者已经不主推。

二、模块

1.配置

.json5文件为配置文件,分为:
app.json5:app级别的配置
module.json5:模块级别的配置

示例:

{
  "module": {
    // ...
    "abilities": [
      {
        // $开头的为资源值
        "icon": "$media:icon",
        "label": "$string:EntryAbility_label",
        "skills": [
          {
            "entities": [
              "entity.system.home"
            ],
            "actions": [
              "action.system.home"
            ]
          }
        ],
      }
    ]
  }
}

通过json文件来配置,也是和之前

2.UIAbility

是什么?
类似Activity

1.生命周期

在这里插入图片描述

onNewIntent等生命周期是否有?
有,见如下

2.启动模式

singleton(单实例模式):与Android一致,配置文件中配置
multiton(多实例模式):对应Android的standard
specified(指定实例模式):对Ability标记key,一致的key则是统一Ability。

针对第三种模式示例:
1.配置

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

2.启动

// 在启动指定实例模式的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) => {
    // ...
})

这里可以看到,startAbility=startActivity,传递的数据的方式也是类似。

3.监听

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

接受参数是通过onAcceptWant获取,名称也是较为直接。

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

需要注意的是:Android中有栈顶复用模式,这里并没有提出这样的概念。因此不确认指定specified模式之后任务栈的关系,或者有没有任务栈的概念?

3.数据传递

使用EventHub进行数据通信:基于发布订阅模式来实现,事件需要先订阅后发布,订阅者收到消息后进行处理。——EventBus
使用globalThis进行数据同步:ArkTS引擎实例内部的一个全局对象,在ArkTS引擎实例内部都能访问。——全局静态变量
使用AppStorage/LocalStorage进行数据同步:ArkUI提供了AppStorage和LocalStorage两种应用级别的状态管理方案,可用于实现应用级别和UIAbility级别的数据同步。——本地缓存

1.EventHub
订阅:eventhub.on(‘event1’, this.func1);
取消订阅:this.context.eventHub.off(‘event1’);
发送事件: this.context.eventHub.emit(‘event1’);
监听事件: eventhub.on(‘event1’, this.func1);

核心要素和EventBus并无二致。
示例:

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() {
    // ...
  }
}

有些许不同的是订阅对象的获取是内置的:let eventhub = this.context.eventHub;

2. globalThis
在这里插入图片描述

在这里插入图片描述
因为TS的特性,所以自定义属性难免会出现覆盖值的情况。这里是后来者覆盖前者。(Stage模型使用,而且FA 模型已经不主推了,因此后者不用管了)

3. APPStorage和LocalStorage

此处不再赘述。

4.页面启动

  1. 启动应用内的UIAbility及获取结果

需要注意的是,提到了如何销毁发起调用的Ability :

在FuncAbility业务完成之后,如需要停止当前UIAbility实例,在FuncAbility中通过调用terminateSelf()方法实现。

// context为需要停止的UIAbility实例的AbilityContext
this.context.terminateSelf((err) => {
 // ...
});

是finish方法?还是回调销毁发起startAbility的Ability?
类似Android中的finish方法。

获取返回结果的回调

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) => {
    // ...
})

从这里来看,与Android流程一致。

  1. 启动其他应用的UIAbility并获取返回结果

显式Want启动:启动一个确定应用的UIAbility,在want参数中需要设置该应用bundleName和abilityName,当需要拉起某个明确的UIAbility时,通常使用显式Want启动方式。

隐式Want启动:根据匹配条件由用户选择启动哪一个UIAbility,即不明确指出要启动哪一个UIAbility(abilityName参数未设置),在调用startAbility()方法时,其入参want中指定了一系列的entities字段(表示目标UIAbility额外的类别信息,如浏览器、视频播放器)和actions字段(表示要执行的通用操作,如查看、分享、应用详情等)等参数信息,然后由系统去分析want,并帮助找到合适的UIAbility来启动。当需要拉起其他应用的UIAbility时,开发者通常不知道用户设备中应用的安装情况,也无法确定目标应用的bundleName和abilityName,通常使用隐式Want启动方式。

这点与Android理念一致,但是Android高版本好像强制显示启动了?

示例:
1.设置action

{
  "module": {
    "abilities": [
      {
        // ...
        "skills": [
          {
            "entities": [
              // ...
              "entity.system.default"
            ],
            "actions": [
              // ...
              "ohos.want.action.editData"
            ]
          }
        ]
      }
    ]
  }
}

2.发起调用

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.被调用时处理

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.调用方处理返回数据

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) => {
    // ...
})
  1. 启动UIAbility的指定页面
    其实就是针对onNewWant回调的处理,可以立即为类似触发Android中的onNewIntent的场景。(热启动)

3.ExtensionAbility组件

ExtensionAbility组件是基于特定场景提供的应用组件,以便满足更多的使用场景。
每一个具体场景对应一个ExtensionAbilityType,各类型的ExtensionAbility组件均由相应的系统服务统一管理,例如InputMethodExtensionAbility组件由输入法管理服务统一管理。当前支持的ExtensionAbility类型有:
FormExtensionAbility:FORM类型的ExtensionAbility组件,用于提供服务卡片场景相关能力。
WorkSchedulerExtensionAbility:WORK_SCHEDULER类型的ExtensionAbility组件,用于提供延迟任务注册、取消、查询的能力。

倒是不像四大组件的定义,毕竟偏向于UI 层面。

三、总结

UIAbility约等于Activity


http://www.niftyadmin.cn/n/5408614.html

相关文章

图书馆管理系统(1)

图书馆管理系统的框架图 图书馆管理系统的基本的功能代码,就是围绕上面这幅图的内容来写, 其中大一点的模块相当于主菜单,小一点的模块相当于子菜单,那就有了主菜单和子菜单如何响应(主到子,子回主&#…

leetcode 121.买卖股票的最佳时机

声明:以下仅代表个人想法,非官方答案或最优题解! 题目: 给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。 你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的…

华为设备总部与分部配置

1.要求: (1)总部实现高可靠性设计,接入层断掉一根线或汇聚、核心设备故障都不能影响数据正常转发 (2)分部1人数较少,采用单臂路由互通 (3)总部、分部1、2之间都能访问互联…

文件操作与IO(3) 文件内容的读写——数据流

目录 一、流的概念 二、字节流代码演示 1、InputStream read方法 第一个没有参数的版本: 第二个带有byte数组的版本: 第三个版本 搭配Scanner的使用 2、OutputStream write方法 第一个版本: 第二个写入整个数组版本: …

AWS MSK的连接

kafka客户端需要Java依赖,所以先安装Java11, sudo yum install java-11https://docs.aws.amazon.com/zh_cn/msk/latest/developerguide/port-info.html 匿名连接 # 匿名使用9092端口 BootstrapServerStringb-2.xxxx.kafka.cn-north-1.amazonaws.com.c…

算法|344.反转字符串 541. 反转字符串II 卡码网:54.替换数字 151.翻转字符串里的单词 卡码网:55.右旋转字符串

344.反转字符串 考察reverse, 也可以用其他方法 /** * param {character[]} s* return {void} Do not return anything, modify s in-place instead.*/ var reverseString function (s) {return s.reverse(); };541. 反转字符串 思路: 一般是i&#…

MVCC及其原理

1. MVCC概述及其原理 多版本并发控制(MVCC,Multi-Version Concurrency Control)是一种数据库管理技术,用于提高数据库系统在多用户环境中的并发性能,同时保证事务的隔离性,避免了不必要的锁定。MVCC允许在…

continue、break 和 return 的区别是什么?

continue、break和return同样是用于控制程序流程的关键字,它们有不同的作用和用法。 continue: 在Java中,continue语句同样通常用于循环结构(如for循环、while循环)。当程序执行到continue时,会立刻跳过当前循环中剩…