鸿蒙技术分享:❓❓[鸿蒙应用开发]怎么更好的管理模块生命周期?
鸿蒙HarmonyOS NEXT应用开发架构设计-模块生命周期管理
模块化开发
模块化开发已经是应用开发中的一个共识,一般对于公司级的应用开发,都会考虑是否可以进行模块化开发。
HarmonyOS NEXT系统应用开发目前使用的Stage模型其实就有涉及模块化开发的部分,比如HAP、UIAbility。
但是,官方模式总是存在一些莫名其妙的问题。
HAP
官方对于通过HAP进行模块化开发的场景见MultiHap。
使用多HAP时,那最常见的HAP见跳转如何处理?
使用Want跳转到其他的Ability:在entry模块的index.ets中通过common.UIAbilityContext()配置Want,作为多hap间信息传递的载体,用于应用组件间的信息传递;
新hap的跳转:在entry模块index.ets首页中,在按钮.onclick()事件内,通过Want配置显式拉起一个新的指定的Ability。
例如:以配置videoFeature模块Want配置为例,在触发按钮事件中加入配置的Want:
· btn.onClick(() => {this.context.startAbility({ bundleName: BUNDLE_NAME, abilityName: AUDIO_ABILITY_NAME }}
· 其中bundleName为appscope文件夹下app.json5中"bundleName": "com.samples.multihap"。
· abilityName为videoFeature模块src/main/module.json5中abilities:["name": "VideoAbility"]
也就是跨模块跳转需要用startAbility。
而正常的页面跳转是用router或者Navigation。
这样就存在方案的不一致性,在做统一的路由管理时反而不方便。
AbilityStage组件容器
上面的HAP方案是基于应用包结构的。
而Stage开发模型和应用包结构不等同,官方文档也是分开讲述的。
多HAP方案对于模块生命周期的使用,其实也是基于UIAbility的。
而UIAbility其实是不唯一的,就算是在一个HAP中也可能存在多个。那么严格来说,用UIAbility来进行模块生命周期管理其实也不足够恰当。
而Stage模型中也有一个专门的模块级别容器,专门用来托管模块的生命周期,AbilityStage组件容器。
AbilityStage是一个Module级别的组件容器,应用的HAP在首次加载时会创建一个AbilityStage实例,可以对该Module进行初始化等操作。
AbilityStage与Module一一对应,即一个Module拥有一个AbilityStage。
所以,当你采用多HAP方案进行模块化开发时,其实更应该用AbilityStage进行生命周期管理。
自主管理模块生命周期
那么除了HAP,还有没有其他的模块生命周期管理方案呢?
有的。
/*** Register ability lifecycle callback.** @param { 'abilityLifecycle' } type - abilityLifecycle.* @param { AbilityLifecycleCallback } callback - The ability lifecycle callback.* @returns { number } Returns the number code of the callback.* @throws { BusinessError } 401 - Parameter error. Possible causes: 1.Mandatory parameters are left unspecified. 2.Incorrect parameter types.* @syscap SystemCapability.Ability.AbilityRuntime.Core* @stagemodelonly* @crossplatform* @atomicservice* @since 11*/on(type: 'abilityLifecycle', callback: AbilityLifecycleCallback): number;
系统其实开放了Ability级别的生命周期方法监听,你可以通过注册的方式托管系统的生命周期管理方法,然后用自己的逻辑进行处理。
比如:
- 自定义一个
ModuleLifecycleManager类,通过监听方法接管生命周期管理。 ModuleLifecycleManager类增加管理方法,允许自主添加具体模块的实例。ModuleLifecycleManager类内部在触发相关方法时,遍历调用已添加模块的同名方法。- 可以使用HSP、HAR作为模块,只需要在模块中创建模块实例,并添加到
ModuleLifecycleManager类中;
参考实现
import LinkedList from '@ohos.util.LinkedList'
import AbilityLifecycleCallback from '@ohos.app.ability.AbilityLifecycleCallback';
import UIAbility from '@ohos.app.ability.UIAbility';
import window from '@ohos.window';
import { Context } from '@ohos.abilityAccessCtrl';export declare class CustomAbilityLifecycleCallback extends AbilityLifecycleCallback {lazyInit(context : Context): void;onRegiste?(context : Context): void;
}export class ModuleLifecycleManager {private constructor() {}private static instance: ModuleLifecycleManagerprivate lifecycleId = 0context?: Contextpublic static getInstance(): ModuleLifecycleManager {if (!ModuleLifecycleManager.instance) {ModuleLifecycleManager.instance = new ModuleLifecycleManager()}return ModuleLifecycleManager.instance}async init(context: Context, moduleFiles?: Array<Promise<ESObject>>) {this.context = contexttry {for (let item of moduleFiles) {await item.then((result: ESObject) => {result.registerAbilityLifecycleCallback()}).catch((error: ESObject) => {})}this.lifecycleId = this.context?.getApplicationContext().on('abilityLifecycle', abilityLifecycleCallback);} catch (paramError) {console.error(`error: ${paramError.code}, ${paramError.message}`);}}async append(moduleFiles?: Array<Promise<ESObject>>) {try {for (let item of moduleFiles) {await item.then((result: ESObject) => {result.registerAbilityLifecycleCallback()}).catch((error: ESObject) => {})}} catch (paramError) {console.error(`error: ${paramError.code}, ${paramError.message}`);}}unInit() {this.context?.getApplicationContext().off("abilityLifecycle", this.lifecycleId)}agreePrivacyPolicy() {for (let item of this.abilityLifecycleCallbacks) {item.lazyInit(this.context!)}}private abilityLifecycleCallbacks = new LinkedList<CustomAbilityLifecycleCallback>()getAbilityLifecycleCallbacks(): LinkedList<CustomAbilityLifecycleCallback> {return this.abilityLifecycleCallbacks}registerAbilityLifecycleCallback(abilityLifecycleCallback: CustomAbilityLifecycleCallback) {this.abilityLifecycleCallbacks.add(abilityLifecycleCallback)if (abilityLifecycleCallback.onRegiste != undefined) {abilityLifecycleCallback.onRegiste(this.context)}}unRegisterAbilityLifecycleCallback(abilityLifecycleCallback: CustomAbilityLifecycleCallback) {this.abilityLifecycleCallbacks.remove(abilityLifecycleCallback)}
}let abilityLifecycleCallback: AbilityLifecycleCallback = {onAbilityCreate: function (ability: UIAbility): void {for (let item of ModuleLifecycleManager.getInstance().getAbilityLifecycleCallbacks()) {item?.onAbilityCreate(ability)}},onWindowStageCreate: function (ability: UIAbility, windowStage: window.WindowStage): void {for (let item of ModuleLifecycleManager.getInstance().getAbilityLifecycleCallbacks()) {item?.onWindowStageCreate(ability, windowStage)}},// 其他方法省略...
}
总结
鸿蒙官方文档中罗列了太多的概念,HAP/HSP/HAR、Entry/feature、Application/Ability/Window/Stage,其实对于正常开发模式的讲解并不清晰。
而且build-profile.json5/module.json5等配置化的开发模式对于应用开发架构的灵活性有很大限制。
就像router/Navigation的路由表配置那样,一旦涉及配置文件,最终的方案基本都会归拢到hvigor插件上,而不是纯代码的运行时。
配置化和运行时各自可能有利有弊吧,本文仅提供一种新的架构解决方案供大家参考。
相关文章:
鸿蒙技术分享:❓❓[鸿蒙应用开发]怎么更好的管理模块生命周期?
鸿蒙HarmonyOS NEXT应用开发架构设计-模块生命周期管理 模块化开发 模块化开发已经是应用开发中的一个共识,一般对于公司级的应用开发,都会考虑是否可以进行模块化开发。 HarmonyOS NEXT系统应用开发目前使用的Stage模型其实就有涉及模块化开发的部分…...
深度解析 Ansible:核心组件、配置、Playbook 全流程与 YAML 奥秘(上)
文章目录 一、ansible的主要组成部分二、安装三、相关文件四、ansible配置文件五、ansible 系列 一、ansible的主要组成部分 ansible playbook:任务剧本(任务集),编排定义ansible任务集的配置文件,由ansible顺序依次执…...
LabVIEW气缸摩擦力测试系统
基于LabVIEW的气缸摩擦力测试系统实现了气缸在不同工作状态下摩擦力的快速、准确测试。系统由硬件平台和软件两大部分组成,具有高自动化、精确测量和用户友好等特点,可广泛应用于精密机械和自动化领域。 项目背景: 气缸作为舵机关键部件…...
Leetcode. 688骑士在棋盘上的概率
题目描述 原题链接:Leetcode. 688骑士在棋盘上的概率 解题思路 多元dp 将dp[step][i][j])定义为从(i, j)出发,走step步之后骑士还在棋盘上的概率。 如果 ( i , j ) (i,j) (i,j)不在棋盘上,即非 0 < i < n 0<i<n 0<i<…...
TCP/IP 协议栈高效可靠的数据传输机制——以 Linux 4.19 内核为例
TCP/IP 协议栈是一种非常成熟且广泛使用的网络通信框架,它将复杂的网络通信任务分成多个层次,从而简化设计,使每一层的功能更加清晰和独立。在经典的 TCP/IP 协议栈中,常见的分层为链路层、网络层、传输层和应用层。本文将对每一层的基本功能进行描述,并列出对应于 Linux …...
Ubuntu22.04搭建LAMP环境(linux服务器学习笔记)
目录 引言: 一、系统更新 二、安装搭建Apache2 1.你可以通过以下命令安装它: 2.查看Apache2版本 3.查看Apache2运行状态 4.浏览器访问 三、安装搭建MySQL 1.安装MySQL 2.查看MySQL 版本 3.安全配置MySQL 3.1是否设置密码?(按y|Y表…...
鸿蒙面试---1208
HarmonyOS 三大技术理念 分布式架构:HarmonyOS 的分布式架构使得设备之间能够无缝协同工作。例如,它允许用户在不同的智能设备(如手机、平板、智能手表等)之间共享数据和功能。比如,用户可以在手机上开始编辑文档&…...
java基础教程第16篇( 正则表达式)
Java 正则表达式 正则表达式定义了字符串的模式。 正则表达式可以用来搜索、编辑或处理文本。 正则表达式并不仅限于某一种语言,但是在每种语言中有细微的差别。 Java 提供了 java.util.regex 包,它包含了 Pattern 和 Matcher 类,用于处理正…...
Docker部署的gitlab升级的详细步骤(升级到17.6.1版本)
文章目录 一、Gitlab提示升级信息二、老版本的docker运行gitlab命令三、备份老版本Gitlab数据四、确定升级路线五、升级(共分3个版本升级)5.1 升级第一步(17.1.2 > 17.3.7)5.2 升级第二步(17.3.7 > 17.5.3)5.3 升级第三步(17.5.3 > 17.6.1) 六、web端访问gitlab服务 一…...
【如何制定虚拟货币的补仓策略并计算回本和盈利】
在虚拟货币市场中,价格波动性极大,如何在波动中生存并获得盈利是每个投资者都在思考的问题。作为一种投资策略,补仓(又称“摊低成本”)常常被用来降低持仓成本,并在市场回升时获得更大的盈利。但如何科学地设定补仓计划,确定回本点和盈利目标呢? 本文将以 Dogecoin 为…...
给图像去除水印攻
去除水印的过程与添加水印相反,它涉及到图像修复、颜色匹配和区域填充等技术。OpenCV-Python 提供了多种方法来处理不同类型的水印,包括但不限于纯色水印、半透明水印以及复杂背景上的水印。下面将详细介绍几种常见的去水印策略,并给出具体的…...
Linux之封装线程库和线程的互斥
Linux之封装线程库和线程的互斥与同步 一.封装线程库二.线程的互斥2.1互斥量的概念2.2初始化和销毁互斥量2.3加锁和解锁2.4互斥量的原理2.5可重入和线程安全2.6死锁 一.封装线程库 其实在我们C内部也有一个线程库而C中的线程库也是封装的原生线程库的函数,所以我们…...
PH热榜 | 2024-12-08
1. Reforged Labs 标语:轻松为手游工作室制作AI广告。 介绍:Reforged Labs 推出了一款前所未有的AI视频制作服务。我们自动化了以往昂贵且耗时的创意流程,取而代之的是能快速、低成本地为各个工作室量身定制视频广告。 产品网站࿱…...
LeetCode刷题day20——贪心
LeetCode刷题day20——贪心 435. 无重叠区间763. 划分字母区间分析: 56. 合并区间分析: 435. 无重叠区间 给定一个区间的集合 intervals ,其中 intervals[i] [starti, endi] 。返回 需要移除区间的最小数量,使剩余区间互不重叠 …...
CCF编程能力等级认证GESP—C++3级—20241207
CCF编程能力等级认证GESP—C3级—20241207 单选题(每题 2 分,共 30 分)判断题(每题 2 分,共 20 分)编程题 (每题 25 分,共 50 分)数字替换打印数字 单选题(每题 2 分,共 …...
Microi 吾码:大数据浪潮中的智能领航者
目录 一、大数据时代的挑战与机遇 二、Microi 吾码在大数据存储方面的应用 与分布式文件系统的集成 数据库存储优化 三、Microi 吾码在大数据处理与分析中的应用 数据清洗与转换 数据分析与挖掘 四、Microi 吾码在大数据可视化中的应用 五、Microi 吾码在大数据流式处…...
Lua语言入门 - Lua 数组
Lua 数组 数组,就是相同数据类型的元素按一定顺序排列的集合,可以是一维数组和多维数组。 在 Lua 中,数组不是一种特定的数据类型,而是一种用来存储一组值的数据结构。 实际上,Lua 中并没有专门的数组类型ÿ…...
gulp应该怎么用,前端批量自动化替换文件
背景 最近公司准备把所有项目中用到的国际化相关的key规范化,原因是: 一直以来公司的app和web端 在针对相同的需求以及相同的国际化语言,需要设置不同的两份国际化文件,难以维护旧版的国际化文件中,存在的大量值重复,…...
石岩湿地公园的停车场收费情况
周末石岩湿地公园停车场【967个】小车停车费封顶14元价格还行,我还记得2020年的时候湿地公园还是10元一天封顶。现在的收费情况也是可以的,尤其是周末停车比工作日停车便宜还是很得民心的哈。 车型 收费标准 小车 工作日 高峰时间8:00~20:00 首小时…...
A7157 基于Java+SSM+mysql+jsp的医院挂号系统的设计与实现 源码 文档 配置 全套资料
医院挂号系统 1.项目描述2. 绪论3.项目功能4.界面展示5.源码获取 1.项目描述 摘 要 随着计算机和网络技术的飞速发展,医院管理与互联网的结合也越来越紧密,享受便捷的医疗服务也变成了人民群众关注的重点。通过对医院就诊挂号情况的调查分析,…...
python/java环境配置
环境变量放一起 python: 1.首先下载Python Python下载地址:Download Python | Python.org downloads ---windows -- 64 2.安装Python 下面两个,然后自定义,全选 可以把前4个选上 3.环境配置 1)搜高级系统设置 2…...
C++.OpenGL (10/64)基础光照(Basic Lighting)
基础光照(Basic Lighting) 冯氏光照模型(Phong Lighting Model) #mermaid-svg-GLdskXwWINxNGHso {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-GLdskXwWINxNGHso .error-icon{fill:#552222;}#mermaid-svg-GLd…...
如何在最短时间内提升打ctf(web)的水平?
刚刚刷完2遍 bugku 的 web 题,前来答题。 每个人对刷题理解是不同,有的人是看了writeup就等于刷了,有的人是收藏了writeup就等于刷了,有的人是跟着writeup做了一遍就等于刷了,还有的人是独立思考做了一遍就等于刷了。…...
C#中的CLR属性、依赖属性与附加属性
CLR属性的主要特征 封装性: 隐藏字段的实现细节 提供对字段的受控访问 访问控制: 可单独设置get/set访问器的可见性 可创建只读或只写属性 计算属性: 可以在getter中执行计算逻辑 不需要直接对应一个字段 验证逻辑: 可以…...
【Android】Android 开发 ADB 常用指令
查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...
怎么让Comfyui导出的图像不包含工作流信息,
为了数据安全,让Comfyui导出的图像不包含工作流信息,导出的图像就不会拖到comfyui中加载出来工作流。 ComfyUI的目录下node.py 直接移除 pnginfo(推荐) 在 save_images 方法中,删除或注释掉所有与 metadata …...
Neko虚拟浏览器远程协作方案:Docker+内网穿透技术部署实践
前言:本文将向开发者介绍一款创新性协作工具——Neko虚拟浏览器。在数字化协作场景中,跨地域的团队常需面对实时共享屏幕、协同编辑文档等需求。通过本指南,你将掌握在Ubuntu系统中使用容器化技术部署该工具的具体方案,并结合内网…...
Java 与 MySQL 性能优化:MySQL 慢 SQL 诊断与分析方法详解
文章目录 一、开启慢查询日志,定位耗时SQL1.1 查看慢查询日志是否开启1.2 临时开启慢查询日志1.3 永久开启慢查询日志1.4 分析慢查询日志 二、使用EXPLAIN分析SQL执行计划2.1 EXPLAIN的基本使用2.2 EXPLAIN分析案例2.3 根据EXPLAIN结果优化SQL 三、使用SHOW PROFILE…...
文件上传漏洞防御全攻略
要全面防范文件上传漏洞,需构建多层防御体系,结合技术验证、存储隔离与权限控制: 🔒 一、基础防护层 前端校验(仅辅助) 通过JavaScript限制文件后缀名(白名单)和大小,提…...
写一个shell脚本,把局域网内,把能ping通的IP和不能ping通的IP分类,并保存到两个文本文件里
写一个shell脚本,把局域网内,把能ping通的IP和不能ping通的IP分类,并保存到两个文本文件里 脚本1 #!/bin/bash #定义变量 ip10.1.1 #循环去ping主机的IP for ((i1;i<10;i)) doping -c1 $ip.$i &>/dev/null[ $? -eq 0 ] &&am…...
