写点什么

【HarmonyOS 5】鸿蒙中的 UIAbility 详解(二)

作者:GeorgeGcs
【HarmonyOS 5】鸿蒙中的UIAbility详解(二)

【HarmonyOS 5】鸿蒙中的 UIAbility 详解(二)

一、前言

今天我们继续深入讲解 UIAbility,根据下图可知,在鸿蒙中 UIAbility 继承于 Ability,开发者无法直接继承 Ability。只能使用其两个子类:UIAbility 和 ExtensionAbility。



本文将对 UIAbility 的三种启动模式,数据如何传递,订阅 UIAbility 生命周期变化,订阅设备的信息变化进行讲解。

二、UIAbility 的三种启动模式

singleton(单实例模式),说人话就是单例模式,App 任务进度中该 UIAbilty 只能存在一个。


multiton(多实例模式),说人话就是单例模式,App 任务进度中该 UIAbilty 能存在多个。


specified(指定实例模式),这玩意就有点复杂了,参见下图,主要通过唯一标识 key 来作为判断量,看该 UIAbility 是创建新的,还是使用已创建的。



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


{  "module": {    // ...    "abilities": [      {        "launchType": "singleton",        // ...      }    ]  }}
复制代码

三、UIAbility 的数据如何传递

一般而言,UIAbility 的数据传递有两种场景:1、A UIAbility 数据传递给 B UIAbility。2、A UIAbility 数据传给内部的 page 或者自定义 view。


同样通用数据传递的方式有以下三种方式进行:1. 单例对象维护数据通过单例对象和注册回调的机制,将数据进行传导:



export class EventDataMgr {
private static mEventDataMgr : EventDataMgr | null = null;
// 需要处理的数据 public mData: XXX | null = null;
/** * 获取实例 * @returns */ public static Ins(){
if(!EventDataMgr .mEventDataMgr ){ EventDataMgr .mEventDataMgr = new EventDataMgr(); } return EventDataMgr .mEventDataMgr; }}
复制代码


2. EventHub,Emitter 我是不建议使用 Emitter 作为数据传递方案,因为它太重了,使用起来也没有 EventHub 方便。


而 EventHub 是从 context 中获取,所以在多 Ability 数据共享场景中,需要对 EventHub 做唯一性处理


import { common } from '@kit.AbilityKit';
export class EventHubUtils {
private static mEventHub: common.EventHub | null = null;
/** * 获取事件通知实例 * @returns */ public static getEventHub(){ // 封装唯一性。因为在不同window中会导致获取的eventhub 不是一个。 if(!EventHubUtils.mEventHub){ let context = getContext() as common.UIAbilityContext; EventHubUtils.mEventHub = context.eventHub; console.log("EventHubUtils", "EventIns mEventHub done !"); } return EventHubUtils.mEventHub; }}
复制代码


3. AppStroage 或者 LocalStroageAppStroage 主要用于多 UIAbility 共享数据进行传递的业务场景。LocalStroage 用于 UIAbility 内部到 page 或者自定义 view 进行传递传递的业务场景。


import { UIAbility } from '@kit.AbilityKit';import { hilog } from '@kit.PerformanceAnalysisKit';import { window } from '@kit.ArkUI';
export default class EntryAbility extends UIAbility {
storage: LocalStorage = new LocalStorage();
onWindowStageCreate(windowStage: window.WindowStage): void { windowStage.loadContent('pages/Index', this.storage, (err) => { if (err.code) { hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? ''); return; } hilog.info(0x0000, 'testTag', 'Succeeded in loading the content.'); }); }
}
复制代码

四、订阅 UIAbility 生命周期变化

该场景主要用于统计 SDK 或者三方应用自己进行业务用户时长交互的数据统计工作。


当进程内的 UIAbility 生命周期变化时,如创建、可见/不可见、获焦/失焦、销毁等,会触发相应的回调函数。每次注册回调函数时,都会返回一个监听生命周期的 ID,此 ID 会自增+1。当超过监听上限数量 2^63-1 时,会返回-1。


import { AbilityConstant, AbilityLifecycleCallback, UIAbility, Want } from '@kit.AbilityKit';import { hilog } from '@kit.PerformanceAnalysisKit';import { window } from '@kit.ArkUI';import  { BusinessError } from '@kit.BasicServicesKit';

const TAG: string = '[LifecycleAbility]';const DOMAIN_NUMBER: number = 0xFF00;

export default class LifecycleAbility extends UIAbility { // 定义生命周期ID lifecycleId: number = -1;

onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void { // 定义生命周期回调对象 let abilityLifecycleCallback: AbilityLifecycleCallback = { // 当UIAbility创建时被调用 onAbilityCreate(uiAbility) { hilog.info(DOMAIN_NUMBER, TAG, `onAbilityCreate uiAbility.launchWant: ${JSON.stringify(uiAbility.launchWant)}`); }, // 当窗口创建时被调用 onWindowStageCreate(uiAbility, windowStage: window.WindowStage) { hilog.info(DOMAIN_NUMBER, TAG, `onWindowStageCreate uiAbility.launchWant: ${JSON.stringify(uiAbility.launchWant)}`); hilog.info(DOMAIN_NUMBER, TAG, `onWindowStageCreate windowStage: ${JSON.stringify(windowStage)}`); }, // 当窗口处于活动状态时被调用 onWindowStageActive(uiAbility, windowStage: window.WindowStage) { hilog.info(DOMAIN_NUMBER, TAG, `onWindowStageActive uiAbility.launchWant: ${JSON.stringify(uiAbility.launchWant)}`); hilog.info(DOMAIN_NUMBER, TAG, `onWindowStageActive windowStage: ${JSON.stringify(windowStage)}`); }, // 当窗口处于非活动状态时被调用 onWindowStageInactive(uiAbility, windowStage: window.WindowStage) { hilog.info(DOMAIN_NUMBER, TAG, `onWindowStageInactive uiAbility.launchWant: ${JSON.stringify(uiAbility.launchWant)}`); hilog.info(DOMAIN_NUMBER, TAG, `onWindowStageInactive windowStage: ${JSON.stringify(windowStage)}`); }, // 当窗口被销毁时被调用 onWindowStageDestroy(uiAbility, windowStage: window.WindowStage) { hilog.info(DOMAIN_NUMBER, TAG, `onWindowStageDestroy uiAbility.launchWant: ${JSON.stringify(uiAbility.launchWant)}`); hilog.info(DOMAIN_NUMBER, TAG, `onWindowStageDestroy windowStage: ${JSON.stringify(windowStage)}`); }, // 当UIAbility被销毁时被调用 onAbilityDestroy(uiAbility) { hilog.info(DOMAIN_NUMBER, TAG, `onAbilityDestroy uiAbility.launchWant: ${JSON.stringify(uiAbility.launchWant)}`); }, // 当UIAbility从后台转到前台时触发回调 onAbilityForeground(uiAbility) { hilog.info(DOMAIN_NUMBER, TAG, `onAbilityForeground uiAbility.launchWant: ${JSON.stringify(uiAbility.launchWant)}`); }, // 当UIAbility从前台转到后台时触发回调 onAbilityBackground(uiAbility) { hilog.info(DOMAIN_NUMBER, TAG, `onAbilityBackground uiAbility.launchWant: ${JSON.stringify(uiAbility.launchWant)}`); }, // 当UIAbility迁移时被调用 onAbilityContinue(uiAbility) { hilog.info(DOMAIN_NUMBER, TAG, `onAbilityContinue uiAbility.launchWant: ${JSON.stringify(uiAbility.launchWant)}`); } }; // 获取应用上下文 let applicationContext = this.context.getApplicationContext(); try { // 注册应用内生命周期回调 this.lifecycleId = applicationContext.on('abilityLifecycle', abilityLifecycleCallback); } catch (err) { let code = (err as BusinessError).code; let message = (err as BusinessError).message; hilog.error(DOMAIN_NUMBER, TAG, `Failed to register applicationContext. Code is ${code}, message is ${message}`); }

hilog.info(DOMAIN_NUMBER, TAG, `register callback number: ${this.lifecycleId}`); } //... onDestroy(): void { // 获取应用上下文 let applicationContext = this.context.getApplicationContext(); try { // 取消应用内生命周期回调 applicationContext.off('abilityLifecycle', this.lifecycleId); } catch (err) { let code = (err as BusinessError).code; let message = (err as BusinessError).message; hilog.error(DOMAIN_NUMBER, TAG, `Failed to unregister applicationContext. Code is ${code}, message is ${message}`); } }}
复制代码

五、订阅设备的信息变化

该场景主要是系统配置更新时调用。例如设备的语言环境,设备横竖屏状态,深浅模式等。


在 UIAbility 中 onConfigurationUpdate()回调方法中实现监测系统这些配置信息的变化。


import { AbilityConstant, Configuration, UIAbility, Want } from '@kit.AbilityKit';import { hilog } from '@kit.PerformanceAnalysisKit';

const TAG: string = '[EntryAbility]';const DOMAIN_NUMBER: number = 0xFF00;

let systemLanguage: string | undefined; // 系统当前语言

export default class EntryAbility extends UIAbility { onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void { systemLanguage = this.context.config.language; // UIAbility实例首次加载时,获取系统当前语言 hilog.info(DOMAIN_NUMBER, TAG, `systemLanguage is ${systemLanguage}`); }

onConfigurationUpdate(newConfig: Configuration): void { console.info(`envCallback onConfigurationUpdated success: ${JSON.stringify(config)}`); // 表示应用程序的当前语言,例如“zh"。 let language = config.language; // 表示深浅色模式,默认为浅色。取值范围: // // - COLOR_MODE_NOT_SET:未设置 // // - COLOR_MODE_LIGHT:浅色模式 // // - COLOR_MODE_DARK:深色模式 let colorMode = config.colorMode; // 表示屏幕方向,取值范围: // // - DIRECTION_NOT_SET:未设置 // // - DIRECTION_HORIZONTAL:水平方向 // // - DIRECTION_VERTICAL:垂直方向 let direction = config.direction; let screenDensity = config.screenDensity; let displayId = config.displayId; let hasPointerDevice = config.hasPointerDevice; let fontId = config.fontId; let fontSizeScale = config.fontSizeScale; let fontWeightScale = config.fontWeightScale; let mcc = config.mcc; let mnc = config.mnc; } // ...}
复制代码


发布于: 刚刚阅读数: 7
用户头像

GeorgeGcs

关注

路漫漫其修远兮,吾将上下而求索。 2024-12-24 加入

历经腾讯,宝马,研究所,金融。 待过私企,外企,央企。 深耕大应用开发领域十年。 OpenHarmony,HarmonyOS,Flutter,H5,Android,IOS。 目前任职鸿蒙应用架构师。 HarmonyOS官方认证创作先锋,华为开发专家HDE。

评论

发布
暂无评论
【HarmonyOS 5】鸿蒙中的UIAbility详解(二)_GeorgeGcs_InfoQ写作社区