动态化 - 鸿蒙跨端方案介绍
一、背景
👉 华为在 2023.9.25 官方发布会上宣布,新的鸿蒙系统将不再兼容安卓应用,这意味着,包括京东金融 APP 在内的所有安卓应用,在新的鸿蒙系统上将无法运行,需要重新开发专门适用于新鸿蒙系统的专版 APP。
二、原生适配方案
原生适配方案就是将京东金融 APP 所有业务层及基建层全部使用鸿蒙语言重写,但该方案存在以下三个问题:
1、首次开发成本高:对齐金融 APP 当前能力,1:1 开发鸿蒙版,开发周期长,研发投入巨大。
2、业务迭代成本高:未来,无论是存量业务还是新增业务,都需要在 iOS、Android、Harmony 等多端同时进行,产品沟通、开发、测试、UI 验收成本均会升高。
3、业务发布效率低:业务需求完成后,需要在华为市场提交、审核、发布,发布周期长,且无法做到业务随时发布。
三、动态化适配方案
“动态化”是一个由京东金融大前端团队全自主研发的,一份代码,可以在 iOS、Android、Web 三端运行的跨平台解决方案。
1、方案简介
动态化目前已经具备一份代码在 iOS、Android、H5 三端运行的能力,该方案就是将动态化一码多端能力对接到鸿蒙系统,降低首次适配研发投入;一次开发,四端共用,长期降低业务迭代成本;并且使业务具备随时发布能力。
2、方案实现
在鸿蒙系统实现动态化的流程和安卓端流程相似,但因鸿蒙生态尚未成熟,我们面临着譬如 V8 虚拟机不能直接使用、核心能力层通讯过程复杂、布局库需要移植等一系列难题。
如上图简略所示,动态化在鸿蒙系统的跨端实现大致流程如下
虚拟机层-V8
动态化跨端框架的实现依赖一个能够执行 js 代码的虚拟机,在 iOS 端使用苹果系统提供的 JSCore,在安卓端使用 V8,而鸿蒙系统未提供类似 JSCore 或者 V8 的虚拟机,所以我们需要将 V8 移植到鸿蒙系统,对应上图 V8 For Harmony 部分。
虚拟机对接层
完成 V8 移植后,我们要使用 ArkTS 语言进行 V8 接口的包装和调用以便使用,包括虚拟机对象创建、内存管理、通讯管理等一系列能力,对应上图 ArkTs2V8 部分。
动态化引擎运行
完成 ArkTs2V8 后,我们就可以运行 RomaEngine 文件了,RomaEngine 文件是一个 js 文件,核心职责在于能够生成一颗虚拟 Dom 树(V-Dom),以及进行 V-Dom 树对比从而触发相应页面节点的更新。
通讯层-JSI
RomaEngine 产生 V-Dom 树的过程会逐条触发原生渲染树的节点创建,在 iOS 和 Android 端目前是使用 JSON 描述的方式进行通讯,但在大量数据传输场景存在性能瓶颈,虽然我们使用了一些技术手段进行了优化,但实现成本高,开发者体验差,所以在鸿蒙系统我们决定使用业界先进的 JSI 技术来建立 JS 和原生(C++)通讯,对应上图通讯层 JSI 部分。
原生 SDK 层
通过 JSI 技术我们就可以在 C++语言中收到 JS 发送过来的节点创建的指令,而鸿蒙原生 UI 的语言是 ArkTS,所以需要借助鸿蒙系统提供的 NAPI 接口进行 C++和 ArkTS 语言的通讯,对应上图 NAPI 部分,这样我们就实现了 JS→C++→ArkTS 链路的通讯,当然也需要反向通讯的过程,这两个过程还包括同步通讯、异步通讯等能力,这里就不详细展开了。建立通讯通道后,再借助鸿蒙系统提供的自定义组件嵌套能力,就可以递归形成鸿蒙原生 UI 树。
布局层
我们先将 Yoga 库移植到了鸿蒙系统,在上述形成的鸿蒙原生 UI 树并未做任何的布局处理,借助 Yoga 布局就可以计算出所有 UI 元素最终的位置和大小,这样就完成了整个渲染流程。
交互处理
例如页面上渲染出来的一个按钮,当发生点击事件后,我们需要实现 ArkTS→C++→JS 通讯链路,将点击事件传递给业务方。
3、关键技术
1、V8 虚拟机移植
- 自编译 V8 路线
V8 虚拟机移植到鸿蒙系统是一个动态化必备的高技术门槛卡点任务,若无法突破此任务,动态化鸿蒙系统的跨端则无法实现。 然而 V8 是一个近千万级代码的庞大仓库,需要掌握 CMake、Clang、LLVM、Ninja 等一系列交叉编译知识(嵌入式范畴),对于应用开发者是一个巨大的挑战,通过动态化小组成员的攻坚克难,现已掌握了 V8 虚拟机交叉编译移植技术。
- 华为内置 V8 路线
短期看我们初步掌握了 V8 交叉编译移植技术,但从包大小、稳定性、兼容性、维护成本等维度看,华为厂商内置 V8 是一个具有长期收益的重大事项,通过和华为持续沟通,最终华为将 V8 内置到了操作系统,业界所有类动态化框均可直接使用内置 V8 虚拟机进行跨端框架的适配。
2、通讯方案设计
鸿蒙系统提供了 NAPI 的方式来建立 Arkts 和 C、C++的通讯。动态化的 JSI 通讯,建立了 JS 虚拟机和宿主环境 C++语言的通讯。这样我们就可以建立 JS、C++和 ArkTs 三种语言间的通讯了。
3、页面渲染方案
- 首次渲染
页面渲染的核心流程就是对于三棵树的管理过程,RomaEngine 负责产生 V-Dom Tree;通过 JSI 通道从根节点开始按照父子关系发出 ComponentTree 节点创建命令,最终形成一个和 V-DomTree 结构一致的 ComponentTree,ComponentTree 每个节点都包含了样式、属性、内容等信息;最后通过鸿蒙系统提供的自定义组件嵌套方式将 ComponentTree 映射为 RenderTree,这样就完成了使用鸿蒙原生组件渲染。
- 二次渲染
当业务需要更新页面的时候,会根据新的页面数据重新生成一个新的 V-Dom Tree,和页面旧的 V-Dom Tree 进行对比,最终得到需要更新的节点数组,将这个数组同样通过 JSI 通道发送到 Componet Tree 对应的节点,再查找出在 Render Tree 对应的节点完成页面的节点更新。
4、布局方案
如果节点不经过布局计算,是无法在屏幕正确的位置上显示的,Yoga 库是一个跨平台布局计算库,目前动态化在 iOS 和 Android 端均使用此库进行布局计算,为保证鸿蒙端布局效果和另外两端的一致性,我们成功将 Yoga 库编译成了鸿蒙系统可运行的库,借助 Yoga 进行节点布局计算。
5、更多内容
通过以上流程就完成了一个页面渲染的核心过程,每一个环节都比较复杂,后续我们会以系列文章展开讲解。
除此之外,还需要处理交互事件、动画、生命周期、埋点曝光、组件化、图表等一系列功能,后续也会加入系列文章中。
四、未来规划
自绘方案
除了鸿蒙系统,小米、Vivo 也发布了澎湃 OS、blueOS,如果将来也不兼容安卓,动态化在每个系统都要做一遍和鸿蒙适配类似的工作,并且需要多个端同时长期维护。我们将探索基于 SKIA 技术的自绘制技术,该技术可以实现一份渲染代码,实现在 iOS、Android、HarmonyOS、澎湃 OS、blueOS 以及未来新的系统上的渲染。
转小程序
动态化基于 V-Dom 模式实现跨端的渲染架构,可以实现同样一份代码转换为微信小程序、抖音小程序、百度小程序等,使业务可以低成本快速完成私域投放。
生态扩展
未来的终端设备将形成万物互联的世界,比如华为的手机应用和车机间已经可以无缝流转,动态化将持续探索在更多设备上运行的技术方案!
版权声明: 本文为 InfoQ 作者【京东科技开发者】的原创文章。
原文链接:【http://xie.infoq.cn/article/39435f51f14297eb67d97d257】。文章转载请联系作者。
评论