当前最热的跨平台UI技术无疑非 Flutter 莫属,Flutter通过自绘 UI 组件,构建高质量跨平台组件库,解决了此类框架难以解决的双端一致性, Bridge 通信效率等问题。并提供丰富的 Widget 组件,渲染性与 Native UI 相媲美,掀起了大家对下一代跨平台技术探索的热情。
同时对国内闲鱼、GCanvas、支付宝、Weex 等都投入了不少研究,通过 Flutter 打造自己的渲染引擎,支持 APP 内业务、小程序等业务。基于 Flutter 引擎有哪些误区?有木有性能媲美 Flutter 的跨平台渲染技术?
本文将通过阐述跨平台 UI 框架的的历史、实现原理、技术优劣,并简单进行横向对比,希望能为你在如今纷乱复杂的跨平台 UI 框架选型上提供一些参考意见。
点评:经常有人在即时通讯网的群里或私信我,说基于Hybrid这种方案的移动端APP里能不能对接即时通讯?该使用什么协议通信?TCP?UDP?还是WebSocket?显然,要正确地认识这些问题,对于即时通讯或相关应用的开发者说,了解当前主流的跨平台移动端UI框架技术原理等,是很有必要的,以免在新产品或项目中的技术选型上走弯路。这也是为什么我要整理与此相关的文章的原因所在。
《最火移动端跨平台方案盘点:React Native、weex、Flutter》( 推荐)
《小程序技术始于微信?来看看移动端小程序技术的前世今生!》
第一代跨平台技术主要以 Webview 容器,代表有 PhoneGap/Cordova 。优点:功能丰富,标准强,历史悠久,有强大的前端生态支持;是目前最成功的跨平台渲染容器。支付宝及微信更是以此为载体,打造小程序内核。第一代渲染引擎主要缺点在于性能方面及高级组件方面,流畅性始终与 Native 无法媲美。
为何会这样,我们以 Blink 为例从三个方面来看此原因。
盘点主流移动端跨平台UI技术:实现原理、技术优劣、横向对比等_1.png
▲ Blink基础架构示意图
Android 平台 WebView 采用多进程架构,主要分为:
Browser 进程负责用户输入, Touch 事件处理、平台相关的对接等功能。 Render 进程 Main Thread 负责 JS 的执行, CSS 解析, Layout Paint ,输出 DisplayList 供 CC 使用。 Work Threads 进行图片的编解码。 Compositor Threads 负责 Layer 的合成,和 Tile 分片;将分片输出成 Bitmap 或者 GL 指令,通过 IPC 输出到 GPU Process 。 GPU Process 的 GPUThread 线程负具体指令的绘制,将绘制指令渲染输出到显示器上。
WebView 的渲染一般从载构建成 DOM Tree 开始算起。下图是 Blink 发起一个样式变更,到最终渲染到屏幕上渲染流程。图片来自于 A Pixel Life In Blink 。
盘点主流移动端跨平台UI技术:实现原理、技术优劣、横向对比等_2.png
▲ 一个像素从更新发起到显示的具体流程
下面是 WebView 渲染具体的具体执行的线程模型:
盘点主流移动端跨平台UI技术:实现原理、技术优劣、横向对比等_3.png
WebView 的 JS 执行, DOM 构建, RenderObject 的构建, Layout Paint 都在主线程执行。 Compositor Thread 负责 Layer 合成, Worker Thread 进行图片解码及 GPU 光栅化。 GPU Thread 进行最终的指令合成和渲染显示。
盘点主流移动端跨平台UI技术:实现原理、技术优劣、横向对比等_4.png
上图 Render 进程是与 GPU 进程 GPU Thread 的交互图,WebView 每一帧的更新都需 IPC 调用更新到 GPU Process ,这种 IPC 模型相对线程通信还是比较昂贵的。
HTML5 标准在 Android/iOS 引擎实现不统一, Android 平台 Chrome(blink) , iOS 平台 WKWebview(Webkit) 。
标准的实现难度非常高:
目前从国内来看, UC /阿里云有能力做内核级别的高级定制开发,其它团队难以进行大规模内核级别的高级定制。无线端 Native 平台成熟的 List Scroller Cell 等高性能组件,无法在 WebView 内核级别做有效的支持。以小程序内嵌 NativeView 所需的同层渲染技术为例,在两个平台要做不同的技术实现。 HTML 规范从提出到落地时间非常长,一般 3-5 年后才能普及,业务难以等待。
第二类跨平台框架主要以 Weex/React-Native/ 鸟巢等为代表,这种技术最大化的复用前端的生态和 Native 的生态体系,把 Native View 的高性能组件积累输出给前端的技术体系。此方案和浏览器的最大区别在于 Script 的执行和 Native View 渲染体系。
盘点主流移动端跨平台UI技术:实现原理、技术优劣、横向对比等_5.png
Weex 对外通过 Rax 和 Vue 前端框架进行功能输出,前端框架下有一层 JS Framework 来实现 dom 的功能。 WeexCore 负责基础的 Flex Layout ,然后通过 Component 分别对接到 Android/iOS 的 Platform Native View 体系。
盘点主流移动端跨平台UI技术:实现原理、技术优劣、横向对比等_6.png
▲ Weex 和 WebView 在 JS Execute Layout Paint 线程模型区别
Weex 体系中, JS 的执行在 JS Thread,Layout 执行在独立的 Layout Thread ,渲染执行在系统的 MainThread ,三个线程相互独立,并行执行。在 WebView 的体系中 JS 的执行、 Layout 、 Paint 都在 MainThread ,相互影响,在进行复杂任务时会导致界面卡顿。
Android Native 线程模型和 WebView 线程模型对比如下图:
盘点主流移动端跨平台UI技术:实现原理、技术优劣、横向对比等_7.png
盘点主流移动端跨平台UI技术:实现原理、技术优劣、横向对比等_8.png
两图对比可以看出:
Weex 体系充分将 Native 的 View 体系输出到前端体系中,在进行 Android/iOS Native View 的封装过程中,存在不少难以逾越的障碍。
如:难以磨平的双端一致性问题、复杂样式能力难以实现、 Layout 动画需要执行两次(WeexCore Layout 和 Android Native 本身的 Layout )。组件的封装成本随着复杂度增加也越来越高,难以逾越 Native View 限制提供更细致的 W3C 标准能力。
2018 年 Flutter 横空出世,通过 Dart 语言构建一套跨平台的开发组件,所有组件基于 Skia 引擎自绘,在性能上和 Native 平台的 View 相媲美。引起大家广泛关注,充分验证了通过绘制构建组件做到 Native View 媲美的 UI 渲染引擎的可行性。
盘点主流移动端跨平台UI技术:实现原理、技术优劣、横向对比等_9.png
▲ Flutter基础架构
Flutter 基础架构主要分为三个部分:
a. Flutter 的渲染流水线:
盘点主流移动端跨平台UI技术:实现原理、技术优劣、横向对比等_10.png
▲ Flutter 渲染流水线
Embedber 层收到 VSync 信号,把此信号传递给 Dart VM 中运行 Flutter Framework 。 Dart UI FrameWork 首先处理 Animation 差值,然后更新 Widget Tree ,接着更新 Element Tree ,最后更新 RenderObject Tree ,发起 Paint 流程。再由 SceneBuilder 输出 Layer Tree ,提交到 GPU 线程进行这一帧的阻塞式合成,合成完成后开始下一帧。
b. Android Native 渲染流水线:
盘点主流移动端跨平台UI技术:实现原理、技术优劣、横向对比等_11.jpg
▲ Android Native 渲染流水线
Android 系统 Native View Framework 收到 VSync 信号后,首先进行 Touch、Input 等事件处理,再进行 Animation 的更新处理,之后 View Tree 发起 Measure和 Layout 完成布局过程。通过 Draw 把本次更新的脏节点更新的 DispayList 绘制指令同步到 RenderThread 。 RenderThread 通过 DisplayList 对 RenderNode 更新合成,把指令转换成 OpenGL 绘制指令输出到 GPU , 整个流程和Flutter基本相同。
a)Flutter 和Android 共同点:
b)Flutter 和 Android 不同点:
Flutter 引擎基于 Skia 构建跨平台组件,解决了 Weex 难以解决的双端一致性等问题。
但是:
这些是它相对于 Weex 的不足。
在性能方面, Flutter 和 Weex 解决方案,本质上基本相同,实际页面性能取决于最佳实践,目前实际情况看 Weex 的 NativeView 性能优势更强一些。
Weex 团队、GCanvas 团队、UC 团队、支付宝团队都在研究 Flutter Engine 。
目前主要由 C++ 流和 JavaScript 流两种做法。这两种做法的共同点核心仍采用 Flutter Engine 的渲染流水线,去除 Dart VM ,引入 JavaScript 生态,把 Flutter 标准转换成 W3C 标准对外输出。
下面简单介绍一下这两种做法:
盘点主流移动端跨平台UI技术:实现原理、技术优劣、横向对比等_12.jpg
▲ Flutter体系向前端输出尝试探索
方案一:通过把 Flutter Widget 整个体系采用 TypeScript 重写,来实现 Flutter 的 JavaScript 的化,上层再基于 JavaScript 的 Widget 封装框架。
方案二:通过把 Flutter的 Framework 采用 C++ 重写,在 Widget 上层封装一层 Component 层,完成 Widget 到 W3C 标准层的转换,然后通过 JavaScript Binding 把 HTML 标准讲功能对外输出。
两种方案都难以把 Flutter 整个体系迁移过来,只能挑选核心的组件进行重写,都是非常不错的尝试。
Widget 标准对于前端不友好,因此不少团队开始尝试把 Widget 体系转换成前端标准子集进行功能输出。在完善的 Flutter Widget 的前提下,Flutter Widget 通过 Component 封装转换成前端 HTML5 标准进行输出。
此方式相对 Weex 封装 Android/iOS 平台 Native View 做法,具有解决 Weex 面临的双端一致性的问题优势。
但Weex 从 Native View 到 W3C 的标准转换很难去完美适配,Flutter 的 Widget 实际到 HTML5 标准转换过程中一样会存在。在深层次标准适配时,会出现难以解决的样式和布局能力扩展的问题。由于引擎本身绘制能力可扩展性,这些方面的缺陷相对 Weex 会弱一些。
整体来看:
上面整体介绍了三类主流的跨平台渲染引擎,下面从特点和技术方面来总结上面的跨平台渲染引擎。
盘点主流移动端跨平台UI技术:实现原理、技术优劣、横向对比等_13.jpg
备注: WebView性能目前随着手机性能的提升而逐步提升,在某些高端机上简单页面的性能已经非常流畅,但在复杂页面尤其是有交互的页面和Weex还是有一定的性能差距。
盘点主流移动端跨平台UI技术:实现原理、技术优劣、横向对比等_14.jpg
此表格概括了目前主流的三代跨平台渲染引擎的技术特点。
目前各种渲染引擎并不是一成不变的,都在蓬勃发展。如 Blink 的 Slimming Paint 项目采用和 Native View 相同的策略, Render Layer 只输出 Display List ,由 CC 根据策略是采用 Layer Compositor 还是 Direct GPU Raster 思路? Firefox 的 WebRender 渲染引擎,尝试把 JS 的执行, Layout、Paint 的执行并行化,并采用更高级的 GPU 绘制元素的方式。
相信未来一定会涌出不少优秀的跨平台 UI 渲染引擎。
原文作者:JackJiang
原文链接:http://www.52im.net/forum.php?mod=viewthread&tid=2641&ctid=16
来源:即时通讯网