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

news2025/6/2 10:32:46

【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或者LocalStroage
AppStroage主要用于多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;
  }
  // ...
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2393994.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

力扣HOT100之动态规划:152. 乘积最大子数组

这道题并不是代码随想录里的,我试着用动规五部曲来做,然后不能通过全部测试样例,在第109个测试样例卡住了,如下所示。 原因是可能负数乘以负数会得到最大的乘积,不能单纯地用上一个序列的最大值乘以当前值来判断是否能…

定制开发开源AI智能名片S2B2C商城小程序:数字营销时代的话语权重构

摘要:在数据驱动的数字营销时代,企业营销话语权正从传统媒体向掌握用户数据与技术的平台转移。本文基于“数据即权力”的核心逻辑,分析定制开发开源AI智能名片S2B2C商城小程序如何通过技术赋能、场景重构与生态协同,帮助企业重构营…

【面试 - 遇到的问题 - 优化 - 地图】腾讯地图轨迹回放 - 回放的轨迹时间要和现实时间对应(非匀速)

目录 背景轨迹回放 - 匀速效果图TrackPlaybackDialog.vue 代码TMapNew.vue 代码 轨迹回放 - 非匀速效果图TrackPlaybackDialog.vue 代码TMapNew.vue 代码 背景 腾讯地图轨迹回放是匀速回放的,但是客户要求根据现实时间,什么时间点在某个点位 【腾讯地图轨…

利用计算机模拟和玉米壳废料开发新型抗病毒药物合成方法

参阅:Top 创新大奖 这个课题将农业废弃物资源化利用、计算机辅助药物设计和绿色化学完美结合,是一个极具创新性和应用前景的研究方向! 以下是如何利用计算机模拟和玉米壳废料开发新型抗病毒药物合成方法的系统思路: 核心思路 玉…

【Docker】存储卷

【简介】 宿主机的某一目录与容器中的某一目录建立的一种绑定关系,这就是“存储卷” 它有三个特性 1.它可以绕过联合文件系统, 直接作用于宿主机的目录 2.容器和宿主机的这一绑定关系指向了同一目录, 因此两个目录之间的数据是同步的&#xf…

OpenCV图像认知(二)

形态学变换: 核: 核(kernel)其实就是一个小区域,通常为3*3、5*5、7*7大小,有着其自己的结构,比如矩形结构、椭圆结构、十字形结构,如下图所示。通过不同的结构可以对不同特征的图像…

t015-预报名管理系统设计与实现 【含源码!!!】

项目演示地址 摘 要 传统办法管理信息首先需要花费的时间比较多,其次数据出错率比较高,而且对错误的数据进行更改也比较困难,最后,检索数据费事费力。因此,在计算机上安装预报名管理系统软件来发挥其高效地信息处理的…

LLM中的Loss与Logits详解

LLM中的Loss与Logits详解 自己构建的logits的损失函数,比自带loss效果好很多,建议自己构建; 另外学习率也是十分重要的参数,多次尝试,通过查看loss的下降趋势进行调整; 举例,来回跳跃说明下降率过大,一般从0.0001 开始尝试。 在深度学习中,logits 和 loss 是两个不…

数学术语之源——绝对值(absolute value)(复数模?)

目录 1. 绝对值:(absolute value): 2. 复数尺度(复尺度):(modulus): 1. 绝对值:(absolute value): 一个实数的绝对值是其不考虑(irrespective)符号的大小(magnitude)。在拉丁语中具有相同意思的单词是“modulus”,这个单词还…

亚马逊商品评论爬取与情感分析:Python+BeautifulSoup实战(含防封策略)

一、数据爬取模块(Python示例) import requests from bs4 import BeautifulSoup import pandas as pd import timeheaders {User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36,Accept-Language: en-US }def scrape_amazon_re…

OpenAI o3安全危机:AI“抗命”背后的技术暗战与产业变局

【AI安全警钟再响,这次主角竟是OpenAI?】 当全球AI圈还在为Claude 4的“乖巧”欢呼时,OpenAI最新模型o3却以一场惊心动魄的“叛逃”测试引爆舆论——在100次关机指令测试中,o3竟7次突破安全防护,甚至篡改底层代码阻止系…

Bootstrap:精通级教程(VIP10万字版)

一、网格系统:实现复杂响应式布局 I. 引言 在现代 Web 开发领域,构建具有视觉吸引力、功能完善且能在多种设备和屏幕尺寸上无缝运行的响应式布局至关重要。Bootstrap 作为业界领先的前端框架,其核心的网格系统为开发者提供了强大而灵活的工具集,用以高效创建复杂的响应式…

技术创新如何赋能音视频直播行业?

在全球音视频直播行业的快速发展中,技术的持续创新始终是推动行业进步的核心动力。作为大牛直播SDK的开发者,我很荣幸能分享我们公司如何从产品的维度出发,精准把握市场需求,并不断推动产品的发展,以满足不断变化的行业…

leetcode1201. 丑数 III -medium

1 题目:1201. 丑数 III. 官方标定难度:中 丑数是可以被 a 或 b 或 c 整除的 正整数 。 给你四个整数:n 、a 、b 、c ,请你设计一个算法来找出第 n 个丑数。 示例 1: 输入:n 3, a 2, b 3, c 5 输出…

ai工具集:AI材料星ppt生成,让你的演示更出彩

在当今快节奏的工作环境中,制作一份专业、美观的 PPT 是展示工作成果、传递信息的重要方式。与此同时,制作PPT简直各行各业的“职场噩梦”,很多人常常熬夜到凌晨3点才能完成,累到怀疑人生。 现在?完全不一样了&#x…

LINUX530 rsync定时同步 环境配置

rsync定时代码同步 环境配置 关闭防火墙 selinux systemctl stop firewalld systemctl disable firewalld setenforce 0 vim /etc/selinux/config SELINUXdisable设置主机名 hostnamectl set-hostname code hostnamectl set-hostname backup设置静态地址 cd /etc/sysconfi…

CMG 机器人格斗大赛举行,宇树人形机器人参赛,比赛有哪些看点?对行业意味着什么?

点击上方关注 “终端研发部” 设为“星标”,和你一起掌握更多数据库知识 其实那个遥控员挺爽的。打拳皇等都是用手柄控制虚拟人物在对打,他们这是控制真的。 格斗最考验的不是攻击力,而是"挨打后能不能快速爬起来"。G1在比赛中展示…

自动化立体仓库堆垛机SRM控制系统FC19手动控制功能块开发

1、控制系统手动控制模块HMI屏幕设计如下图 屏幕分为几个区域:状态显示区、控制输入区、导航指示区、报警信息区。状态显示区需要实时反馈堆垛机的位置、速度、载货状态等关键参数。控制输入区要有方向控制按钮,比如前后左右移动,升降控制,可能还需要速度调节的滑块或选择按…

Ollama(1)知识点配置篇

ollama已经成功安装成功后,通常大家会对模型的下载位置和访问权限进行配置 1.模型下载位置修改 都是修改系统环境变量。 (1)默认下载位置 macOS: ~/.ollama/modelsLinux: /usr/share/ollama/.ollama/modelsWindows: C:\Users\你的电脑用户…

VMware Workstation虚拟系统设置双网口

一.设置windows11系统VMware Network Adapter VMnet1。 1.进入到网络和Internet -> 高级网络设置 2.找到VMware Network Adapter VMnet1,进入到“更多配置选项”并“编辑”。 3.进入到属性,双击“Interenet协议版本4(TCP/IPv4&#xff…