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

前提:基于官网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

猜你喜欢

转载自blog.csdn.net/ganshenml/article/details/136329663