Taro 鸿蒙技术内幕系列(三) - 多语言场景下的通用事件系统设计

基于 Taro 打造的京东鸿蒙 APP 已跟随鸿蒙 Next 系统公测,本系列文章将深入解析 Taro 如何实现使用 React 开发高性能鸿蒙应用的技术内幕

背景

在鸿蒙生态系统中,虽然原生应用通常基于 ArkTS 实现,但在实际研发过程中发现,使用 C++ 可以显著提升应用框架和业务的性能表现。随着鸿蒙系统的不断迭代升级,不同语言环境间的协作已成为不可或缺的开发范式,共同构建了更丰富的研发生态。

Taro 通过接入鸿蒙端的 C-API 相关能力,将组件、样式布局等运行时逻辑下沉到 C++ 层,从而极大地提升了页面的渲染性能。

在这样的背景下,构建一套在 C++、ArkTS 等不同语言环境之间高效通信的事件系统,成为了一个极具价值,对于 Taro 来说也是必修的课题。

多语言环境的事件处理机制

在 Harmony 端的适配过程中,事件系统扮演着双重角色:不仅驱动应用、页面和各模块组件的生命周期,还因为 ArkTS 和业务代码(JS)之间存在人为设定的界限,需要事件作为桥梁,以便 JS 能够调用 ArkTS 的原生能力。

跨语言环境事件驱动架构的设计考量

在设计跨语言环境的事件驱动架构时,需要同时考虑 ArkTS、JS 和 C++ 等多个语言环境的限制和运行时差异。如何实现事件在这些环境之间的有序传递,以驱动页面和组件的生命周期,是事件系统设计的重要考量。

mindmap

通过 C++ 实现事件的底层逻辑,构建一个高效的事件管理系统,可以有效避免冗余接口的设计。同时,与鸿蒙的 C-API 支持的事件系统对接,将各类事件分发到不同语言环境,确保跨语言环境的事件分发与处理的有序性、高效性。

roadmap

回顾 Taro 开始适配鸿蒙至今,事件系统也随之经历了从简单到完善的演进历程。从最初在 ArkTS 方案中的基础实现,到随着 Taro for Harmony 方案迭代发展,事件系统的设计也面临 ArkTS 带来的一些限制。

在 ArkTS 语言环境中事件架构的局限性

基于 ArkTS 语言环境实现的事件架构,在性能方面存在较大局限性。特别是在事件冒泡过程中,性能较差的语法,和回调逻辑可能会导致性能严重劣化,甚至阻塞主线程。这不仅会影响应用的响应速度,更有甚者可能对整体用户体验产生负面影响。

single_thread

为了解决这些问题,提升性能以保证用户体验成为关键目标。通过将事件处理逻辑下沉到 C++ 层,并置于后台线程执行等优化手段。能够有效提高代码执行效率,同时避免逻辑阻塞主线程导致的延迟响应,以提升应用的流畅性,提供更佳的用户体验。

mutli_thread

构建多语言环境下的事件系统

在构建多语言环境下的事件系统时,首要考虑各种类型的事件,比如:鸿蒙提供的组件通用事件、手势等。事件系统需要有效地管理这些不同的事件来源,并根据框架和用户的监听行为有序进行事件的分发。

events

在这些事件类型中,大致可以分为普通事件和节点事件两类。前者涵盖系统层面和应用、组件等生命周期的变化,通常由系统或应用状态的改变触发,主要由事件中心(eventCenter)来处理;节点事件则与 DOM Tree 紧密相关,这些事件通常需要快速响应,以确保用户界面的流畅性和交互的即时性。

事件中心(eventCenter)的实现

作为 Taro 运行时中的基础模块,事件中心专注于处理系统事件和生命周期。它允许框架和应用开发者在后台线程注册事件队列,并异步分发事件,从而有效减轻主线程的负担。事件中心能够快速响应各种事件,同时具备健壮的错误处理机制,帮助开发者快速定位和解决事件回调中的问题,从而提升开发效率和系统稳定性。

事件监听与分发

开发者可以在 C++ 和 ArkTS 等多种语言环境中创建事件监听器,并将相应的回调函数添加到事件队列中。这一机制允许开发者在不同的编程语言中灵活地定义和处理事件响应逻辑。

当事件触发时,会根据不同语言环境的运行时差异,将事件参数转换为对应的格式。这种参数转换确保了各语言环境能够正确理解并处理事件及包含的数据,无论是简单的数据类型还是复杂的对象结构,都能在不同语言之间无缝传递。

event_center

事件队列会根据监听器的类型,按照预定义的顺序,将事件分发到相应的语言环境中。这样一来,每个监听器都能在其所属的环境中高效地执行对应的回调函数。通过这种方式,不仅可以实现了跨语言的事件处理,优化事件的分发效率,并确保应用在响应用户交互时保持高性能和高稳定性。

需要注意的是,受限于底层限制,在 ArkTS 环境中注册的事件需要回到主线程执行,同时在鸿蒙端不支持 Symbol 类型的事件。

节点事件处理(domEvent)

在 HTML 中,节点事件处理流程会如下图所示,事件从根节点开始向下传播至目标节点,触发后再从目标节点顺着节点树向上冒泡。在鸿蒙端实现中,Taro 基于这一事件传播流程,为开发者提供一致的事件处理机制。

事件类型

在 Taro 框架中,节点主要处理三种类型的事件:鸿蒙事件、鸿蒙手势事件和自定义事件。这些事件都是从 TaroElement 上进行监听和触发的。根据事件的类型不同,节点会从相应的事件源设置 Receiver (事件接收器)来进行监听并处理回调逻辑。

event_dom

鸿蒙事件和鸿蒙手势事件分别通过 RenderNode 注册到 Receiver,确保事件能够正确地传递和触发。而自定义事件则根据节点实现或用户自行触发,以满足各种不同类型的交互响应。

事件传播

当 TaroElement 上的事件被触发后,事件会沿着节点树向上传播。每个节点依次接收到事件,并执行相应的回调。执行完回调后,会检查开发者是否阻止冒泡,以决定是否继续向上传播。事件从目标节点开始,逐级往上直到根节点或者冒泡被阻止。

html_event


这允许开发者在事件传播过程中,通过任意节点处理或拦截事件来调整业务逻辑实现,以更灵活的方式在特定节点上执行逻辑,或通过阻止冒泡避免对上层节点的影响。这样的设计对于前端开发者来说,更加熟悉、直观。

鸿蒙系统的底层节点事件也有自己的传播逻辑,但由于其机制与 ArkNode 节点树差异,为避免其事件干扰,需要阻止其冒泡行为并接管其传播流程,以确保事件传播与节点树正确关联。

事件回调

由于节点事件也需要回调 JS 环境中执行,根据事件类型的不同,按照 Web 标准将相应的节点、值和方法如 targetstopPropagationvalue 等等挂载到事件对象上。通过执行当前回调的序列化方法,确保事件在不同语言环境传递时,可以保证其回调对象能力一致、参数完整。

在 C++ 中,许多组件依赖于事件机制来实现功能。例如,通过鸿蒙事件更新组件属性,还有各个组件节点间的事件传递等。这些组件利用事件机制来确保数据变化能够及时反映,并且用户交互能够顺利传递到系统的各个部分。

总结与展望

在多语言环境中,确保事件在不同语言环境传递时的一致性尤为重要,各个模块以及应用内不同页面或组件通过事件解耦驱动来提升可维护性。当前的解决方案有效提升了系统的响应速度和模块间的协作能力。

当下方案实现中仍然存在一些问题,比如早期通过事件绕过 ArkTS 与 JS 之间相互调用限制等场景,可以通过 TurboModule 来提供更加直接的调用方案。

未来,在 Taro for Harmony 场景下,各语言模块的协同将进一步增强。基于事件系统的设计,可以有效地解耦模块间逻辑,实现更灵活的组合。

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

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

相关文章

【计算机网络】C/C++实现解析Wireshark离线数据包,附源码

直接先上demo 以下是一个完整的示例代码&#xff0c;演示如何使用 pcap_open_offline 函数打开一个捕获文件并读取数据包。 #include <stdio.h> #include <pcap.h>int main(int argc, char **argv) {if (argc ! 2) {fprintf(stderr, "Usage: %s <capture…

PostgreSQL外键全解析:从概念到实践的进阶指南

全文目录&#xff1a; 开篇语目录前言&#xff1a;关于外键你真的懂了吗&#xff1f;&#x1f914;外键的定义和作用 &#x1f4da;如何在PostgreSQL中创建外键 &#x1f331;基本语法示例&#xff1a;建立简单的外键关系 外键约束的各种行为和选项 &#x1f9e9;ON DELETE 与 …

带有悬浮窗功能的Android应用

android api29 gradle 8.9 要求 布局文件 (floating_window_layout.xml): 增加、删除、关闭按钮默认隐藏。使用“开始”按钮来控制这些按钮的显示和隐藏。 服务类 (FloatingWindowService.kt): 实现“开始”按钮的功能&#xff0c;点击时切换增加、删除、关闭按钮的可见性。处…

Day 27 贪心算法 part01

贪心算法其实就是没有什么规律可言,所以大家了解贪心算法 就了解它没有规律的本质就够了。 不用花心思去研究其规律, 没有思路就立刻看题解。 基本贪心的题目 有两个极端,要不就是特简单,要不就是死活想不出来。 学完贪心之后再去看动态规划,就会了解贪心和动规的区别。…

PyQt5控件QWebEngineView(WebView)

PyQt5控件QWebEngineView(WebView) 下载依赖 PyQt5、PyQtWebEngine pip install --index-urlhttps://mirrors.aliyun.com/pypi/simple/ PyQt5 pip install --index-urlhttps://mirrors.aliyun.com/pypi/simple/ PyQtWebEngine加载外部网页 import sys from PyQt5.QtCore im…

ML 系列:第 36 节 — 统计学中的抽样类型

ML 系列&#xff1a;第 36 天 — 统计学中的抽样类型 文章目录 一、说明二、抽样方法三、简单随机抽样四、 Stratified Sampling分层抽样五、 Cluster Sampling 整群抽样六、Systematic Sampling系统抽样七、Convenience Sampling便利抽样八、结论 一、说明 统计学中的抽样类型…

godot游戏引擎_瓦片集和瓦片地图介绍

在 Godot 中&#xff0c;TileSet 和 TileMap 是用于处理瓦片地图的两个关键概念&#xff0c;它们的作用和用途有明显的区别。以下是两者的详细对比&#xff1a; 1. TileSet&#xff08;瓦片集&#xff09; TileSet 是资源&#xff0c;定义瓦片的内容和属性。 特点&#xff1a…

CGMA – Cloth Creation and Simulation for Real-Time

CGMA – 实时布料创建和模拟 Info&#xff1a; 本课程介绍如何将 Marvelous Designer 整合到布料工作流程中以实时创建角色&#xff0c;从软件基础知识到创建逼真和风格化服装的高级技术。本课程将首先介绍软件&#xff0c;通过创建现代、现代的服装&#xff0c;然后深入探讨使…

Springboot组合SpringSecurity安全插件基于密码的验证Demo

Springboot组合SpringSecurity安全插件基于密码的验证Demo!下面的案例&#xff0c;都是基于数据库mysql&#xff0c;用户密码&#xff0c;验证登录的策略demo。 1&#xff1b;引入maven仓库的坐标 <dependency><groupId>org.springframework.boot</groupId>…

最佳实践:如何在 Vue.js 项目中使用 Jest 进行单元测试

前言 随着应用程序规模和复杂性的增加&#xff0c;保证代码质量和稳定性变得愈发重要。单元测试作为软件测试的一部分&#xff0c;能够有效地捕捉代码中的错误&#xff0c;防止在开发过程中引入新的 Bug。在众多测试框架中&#xff0c;Jest 因其易用性、强大功能以及与 Vue.js…

从Full-Text Search全文检索到RAG检索增强

从Full-Text Search全文检索到RAG检索增强 时光飞逝&#xff0c;转眼间六年过去了&#xff0c;六年前铁蛋优化单表千万级数据查询性能的场景依然历历在目&#xff0c;铁蛋也从最开始做CRUD转行去了大数据平台开发&#xff0c;混迹包装开源的业务&#xff0c;机缘巧合下做了实时…

单片机学习笔记 8. 矩阵键盘按键检测

更多单片机学习笔记&#xff1a;单片机学习笔记 1. 点亮一个LED灯单片机学习笔记 2. LED灯闪烁单片机学习笔记 3. LED灯流水灯单片机学习笔记 4. 蜂鸣器滴~滴~滴~单片机学习笔记 5. 数码管静态显示单片机学习笔记 6. 数码管动态显示单片机学习笔记 7. 独立键盘 目录 0、实现的…

使用 Django 构建支持 Kubernetes API 测试连接的 POST 接口

文章目录 使用 Django 构建支持 Kubernetes API 测试连接的 POST 接口功能需求使用 kubectl 获取 Token命令解析输出示例 完整代码实现Kubernetes API 客户端类功能说明 Django 接口视图关键点解析 路由配置 接口测试请求示例响应结果成功错误 优化建议1. 安全性2. 错误处理3. …

【AI日记】24.11.26 聚焦 kaggle 比赛

【AI论文解读】【AI知识点】【AI小项目】【AI战略思考】【AI日记】 核心工作 1 内容&#xff1a;研究 kaggle 比赛时间&#xff1a;3 小时 核心工作 2 内容&#xff1a;学习 kaggle 比赛 Titanic - Machine Learning from Disaster时间&#xff1a;4 小时备注&#xff1a;这…

排序算法2

排序算法1-CSDN博客 排序算法1中提及的是较为基础(暴力实现&#xff0c;复杂度较高)的排序算法&#xff0c;不适合于数据量较大的场景&#xff0c;比如序列长度达到1e5 接下来以蓝桥另一道题目来理解其它的排序算法 蓝桥3226 蓝桥账户中心 样例 5 1 5 9 3 7 4、快速排序 快速排…

【数据结构实战篇】用C语言实现你的私有队列

&#x1f3dd;️专栏&#xff1a;【数据结构实战篇】 &#x1f305;主页&#xff1a;f狐o狸x 在前面的文章中我们用C语言实现了栈的数据结构&#xff0c;本期内容我们将实现队列的数据结构 一、队列的概念 队列&#xff1a;只允许在一端进行插入数据操作&#xff0c;在另一端…

macos 14.0 Monoma 修改顶部菜单栏颜色

macos 14.0 设置暗色后顶部菜单栏还维持浅色&#xff0c;与整体不协调。 修改方式如下&#xff1a;

长三角文博会:Adobe国际认证体系推动设计人才评价新标准

2024年11月22日&#xff0c;由上海、江苏、浙江、安徽三省一市党委宣传部共同发起的第五届长三角文化博览会&#xff08;简称“长三角文博会”&#xff09;在上海国家会展中心盛大启幕。长三角文博会自2018年起已成功举办多届&#xff0c;已成为展示区域文化产业发展成果、推动…

安装数据库客户端工具

如果没有勾选下面的&#xff0c;可以运行下面的两个命令 红框为自带数据库 新建数据库 右键运行mysql文件&#xff0c;找到数据库&#xff0c;并刷新

SQL 复杂查询

目录 复杂查询 一、目的和要求 二、实验内容 &#xff08;1&#xff09;查询出所有水果产品的类别及详情。 查询出编号为“00000001”的消费者用户的姓名及其所下订单。&#xff08;分别采用子查询和连接方式实现&#xff09; 查询出每个订单的消费者姓名及联系方式。 在…