
Flutter是2018年最热门的跨平台技术,它诞生了. 通过自绘UI组件,构建了高质量的跨平台组件库,以解决此类框架无法解决的双端一致性和Bridge通信效率问题. 并提供丰富的Widget组件,渲染效果可与Native UI媲美,激发了所有人对下一代跨平台技术探索的热情. 同时,他们对家用闲鱼,GCanvas,支付宝,Weex等进行了大量研究android渲染引擎,并通过Flutter构建了自己的渲染引擎,以支持应用程序内业务,小型程序和其他业务. Flutter是下一代跨平台技术吗?基于Flutter引擎的误解是什么?是否存在性能与Flutter相当的跨平台渲染技术?本文阐述了跨平台UI渲染引擎的历史,并通过实践研究探索了下一代跨平台UI渲染引擎的构建.
第一代跨平台技术主要使用以PhoneGap / Cordova为代表的Webview容器. 优势: 功能丰富,标准规范,悠久历史,强大的前端生态支持;是目前最成功的跨平台渲染容器. 支付宝和微信以此为载体创建小程序内核. 第一代渲染引擎的主要缺点是性能和高级组件. 流利性总是与Native不可比拟的.
为什么会这样?让我们以眨眼为例,从三个方面来看这个原因.

闪烁基本架构图
Android平台WebView采用多进程架构,主要分为浏览器进程,渲染进程和GPU进程. 浏览器过程负责用户输入,触摸事件处理,平台相关的停靠和其他功能. 渲染过程Main Thread负责执行JS,CSS解析,Layout Paint,输出DisplayList供CC使用. 工作线程对图片进行编码和解码. 复合线程负责图层合成和切片. 输出切成位图或GL指令的切片,并通过IPC输出到GPU进程. GPU进程的GPUThread绘制否定的特定指令,并将呈现指令呈现到显示器.
WebView的呈现通常从构建DOM树开始. 下图是Blink启动样式更改以最终渲染到屏幕的渲染过程. 图片来自眨眼的像素生活.

从更新开始到显示的特定像素流
以下是WebView渲染的特定执行线程模型:

WebView的JS执行,DOM构造,RenderObject构造和Layout Paint均在主线程上执行. 复合线程负责图层合成,工作线程执行图像解码和GPU光栅化. GPU线程执行最终的指令合成和渲染显示.

上面的渲染过程是与GPU进程GPU线程的交互图. WebView的每次更新都需要IPC调用才能更新到GPU进程. 与线程通信相比,这种IPC模型相对昂贵.
HTML5在Android / iOS引擎实现,Android平台Chrome(闪烁),iOS平台WKWebview(Webkit)中不是统一的. 该标准的实施非常困难. 每个引擎的代码行数为5到1千万行;巨大的代码量导致较高的输入和修改成本,并且引擎定制成本非常复杂. 从国内的角度来看,UC /阿里云能够在内核级别进行高级定制,而其他团队则很难在内核级别上进行高级定制. WebView内核级别无法有效地支持高性能组件,例如无线Native平台上成熟的List Scroller Cell. 以applet中嵌入式NativeView所需的相同层渲染技术为例,在两个平台上必须实现不同的技术. HTML规范从提议到发布的时间很长,通常会在3-5年后普及,这使企业很难等待.
第二种跨平台框架主要以Weex / React-Native / Bird's Nest等为代表. 该技术最大限度地提高了前端生态系统和Native生态系统以及高性能组件的重用性累积了“本地视图”,并输出到前端技术系统. 该解决方案与浏览器之间的最大区别是脚本和Native View渲染系统的执行.


Weex使用Rax和Vue前端框架在外部输出功能. 前端框架下有一层JS框架来实现dom的功能. WeexCore负责基本的Flex布局,然后通过Component连接到Android / iOS的Platform Native View系统.

Wex和WebView在JS中执行Layout Paint线程模型的区别
在Weex系统中,JS是在JS线程中执行的,布局是在独立的布局线程中执行的,而渲染是在系统的MainThread中执行的. 这三个线程彼此独立并且并行执行. 在WebView系统中,JS,Layout和Paint的执行全部在MainThread中,这会相互影响,并且在执行复杂任务时会导致界面冻结.
Android Native线程模型与WebView线程模型之间的比较如下:


可以看到两张图片之间的比较:
Weex系统将Native View系统完全输出到前端系统. 在打包Android / iOS本机视图的过程中,存在许多无法克服的障碍. 例如: 难以解决的双端一致性问题,实现复杂样式的能力难以实现,并且布局需要执行两次(WeexCore Layout和Android Native自己的Layout). 随着复杂性的增加,组件的包装成本也越来越高,从而难以超越Native View的限制并无法提供更详细的W3C标准功能.
2018年,Flutter诞生了,并且通过Dart语言构建了一组跨平台开发组件. 所有组件都是基于Skia引擎自行绘制的,其性能与Native平台View相当. 它引起了广泛的关注,并充分验证了渲染建筑组件以实现与Native View相当的UI渲染引擎的可行性.

Flutter基础架构
Flutter基础结构主要分为三个部分:
框架层: 包含绘画手势,RenderIng小部件和其他模块;提供基本的UI组件.
引擎层包括: Dart VM Manager,Frame Pipeline Rendering,TextLayout和其他模块,主要负责Skia渲染计划和Layer Tree合成.

Embedber层分别连接到Android / iOS平台层,以进行事件停靠,Surface停靠以及由本机平台接口调用的插件机制.
3.2.1 Flutter的渲染管道

Flutter渲染管道
Embedber层接收VSync信号,并将其传递到Dart VM以运行Flutter Framework. Dart UI FrameWork首先处理差异,然后更新小部件树,然后更新元素树,最后更新RenderObject树以启动绘画过程. 然后,SceneBuilder输出“层树”,并将其提交给GPU线程,以阻止该帧的合成. 合成完成后,下一帧开始.
3.2.2 Android Native渲染管道

Android Native渲染管道
收到VSync信号后,Android系统的本机视图框架首先处理诸如触摸和输入之类的事件,然后更新. 然后,“视图树”启动“度量和布局”以完成布局过程. 同步由脏节点更新的DispayList绘图指令,该脏节点通过Draw更新为RenderThread. RenderThread通过DisplayList更新和合成RenderNode,将指令转换为OpenGL绘图指令并将其输出到GPU. 整个过程与Flutter基本相同.
a,Flutter和Android有共同点:
使用简化的渲染管道,从事件到GPU更新的整个渲染过程非常相似
在GPU级别进行直接栅格化,以充分利用现代GPU的高性能渲染性能.
使用OpenGL共享上下文进行设计,异步纹理上传以及共享纹理资源(例如图片).
最新版的Android Native和Flutter使用Skia引擎进行合成绘图.
B,Flutter和Android不同:
Android Native使用Java构建UIFramework,Flutter使用Dart.

Android Native支持部分更新,并在Open GL级别上进行了许多深度优化. 目前Flutter的工作还不够.
Android HW UI是一个系统应用程序android渲染引擎,可以根据手机型号和GPU进行优化和深度定制; Flutter框架无法做到这一点.
目前,Android生态用户界面库较为全面,模块之间的集成成本较低. Flutter是独立的,与Native View集成需要一定的成本.
Flutter引擎基于Skia构建跨平台组件,从而解决了Weex难以解决的双端一致性问题. 上层采用Dart语言,并且没有利用前端最强大的JavaScript生态;与NativeView的集成中还存在一些问题,并且很难重用Native多年来积累的强大组件. 这些是其相对于Weex的缺点. 在性能方面,Flutter和Weex解决方案基本相同. 实际页面性能取决于最佳做法. 目前,Weex的NativeView的实际性能更强.
Weex团队,GCanvas团队,UC团队,支付宝团队都在研究Flutter Engine. 当前,主要有C ++流和JavaScript流两种方法. 这两种做法的共同核心仍然是使用Flutter Engine的渲染管道,删除Dart VM,引入JavaScript生态以及将Flutter标准转换为W3C标准以进行外部输出. 下面简要介绍这两种做法:

Flutter系统输出到前端以尝试探索
解决方案1: 使用TypeScript重写Flutter Widget的整个系统以实现Flutter的JavaScript,并且上层基于JavaScript Widget封装框架.
解决方案2: 通过用C ++重写Flutter Framework,将Component层封装在Widget的上层,以完成Widget到W3C标准层的转换,然后将HTML标准功能输出到通过JavaScript绑定访问外部世界.
这两种解决方案都很难迁移整个Flutter系统,只能选择核心组件进行重写,这是非常好的尝试.
Widget标准对前端不友好,因此许多团队已开始尝试将Widget系统转换为用于功能输出的前端标准的子集. 在完善的Flutter Widget的前提下,Flutter Widget被转换为前端HTML5标准,以通过组件封装输出. 与Weex打包Android / iOS平台Native View的方法相比,此方法具有解决Weex面临的双端一致性问题的优势. Weex从标准视图到W3C的标准转换很难完全适应. Flutter的Widget实际上将在转换为HTML5标准期间存在. 在深层次的标准适应中,将难以解决样式和布局容量扩展的问题. 由于引擎自身渲染功能的可伸缩性,这些缺陷比Weex弱. 总体而言: Widget标准向HTML5标准的转换只能部分实现,很难完美地适应;在组合复杂的样式时,您会遇到与标准的不一致之处,并且很难像下一代的自定义内核UI渲染引擎那样高效.
上面描述了前三种类型的跨平台渲染引擎. 下面从功能和技术方面总结了上述跨平台渲染引擎.

备注: 随着手机性能的提高,WebView的性能逐渐提高. 在某些高端计算机上,简单页面的性能非常流畅,但是Weex和复杂页面之间仍然存在一定的性能差距,尤其是那些具有交互式页面的页面.

此表总结了前三代跨平台渲染引擎的技术特征. 下一代跨平台UI呈现引擎将是什么样?

Web技术是目前最广泛的应用平台,Weex / React-Native / QT等各种技术都将Web技术用作最有效的输出方法. Flutter Widget标准只是Flex的一个子集,而使用Flutter Widget将其转换为HTML的子集不一定是下一代渲染引擎的最佳实践. 下一代渲染引擎应该充分吸收上一代的优势,并继续前进. 下一代跨平台渲染引擎的特点是什么?我个人认为下一代渲染引擎应具有以下特征:
前端设计,支持最广泛的JavaScript语言和某些CSS HTML标准; JS独立执行和Layout分离,并行执行.
专为GPU,轻量级高性能渲染管线而设计.
在内核级别支持Web标准可以完全扩展Web所需的功能,而无需标准的中间转换层,例如Yoga.
除Web标准外,它还支持诸如列表滚动器滑块之类的本机高级组件,以解决复杂页面的性能低下和占用大量内存的问题.
内核支持多种手势,例如PanGesture ScrollGesture ScaleGesture等,并且组件直接在内核级别处理这些手势.

底层布局和样式实现是指Web思想. 除了Web标准之外,还构建了一组高性能UI框架,然后将JS引擎向上停靠在最后一个Rax Vue框架中.

下一代渲染引擎的管道和OpenGL设计
UI框架采用Native Tookit的轻量级渲染管道设计,并在GPU级别执行Direct GPU Raster栅格化. 通过OpenGL共享上下文有效共享纹理资源. 渲染性能与Native View基本相同,创建了轻量级的高性能UI渲染引擎.
1. 专为GPU,Direct GPU栅格而设计;没有考虑CPU方面的综合情况,充分发挥了现代GPU的高性能.
2. 轻量级渲染管道,轻量级“层树”可更有效地响应页面更改.
3. JavaScript是在单独的线程中执行的,而Layout Paint是并行执行的. 繁重的JavaScript任务不会影响用户界面流畅性.
4. 通过Open GL共享上下文进行位图异步上传和纹理资源共享.
5. UI渲染引擎本身不包含Dom,JSBinding等功能,而是专注于高性能UIKit渲染引擎.
6. 基本的布局和样式实现参考Web想法,但是在Web标准之外构建了一套完整的高性能UI框架.
7. 该设计机制消除了WebView快速滑动过程的白屏,并通过高性能UI组件解决了Web性能和内存消耗的问题.
下一代渲染引擎的性能如何?实际可行吗?目前,Demo已完成滚动组件的开发,其滚动流畅度可与Weex Native List和Flutter列表相媲美. 在一些复杂的场景中,它甚至比流利的Weex Native List更好. 在样式功能方面,它远远超过了当前的解决方案,例如Weex / Flutter.
本文主要介绍当前主流的跨平台渲染引擎以及渲染引擎的最新探索. 目前,各种渲染引擎不是一成不变的,并且正在蓬勃发展. 例如,Blink的Slimming Paint项目采用与Native View相同的策略. 渲染层仅输出显示列表. 根据该策略,CC是否使用Layer Compositor或Direct GPU Raster? Firefox的WebRender渲染引擎尝试并行执行JS,Layout和Paint,并使用更高级的GPU绘制元素. 我相信,将来会有很多出色的跨平台UI呈现引擎.
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-187971-1.html
我们家千玺配的棒棒的