在进入正文之前需要先解释下什么是【小部件】,小部件是淘宝模块/卡片级的开放解决方案,其主要面向私域提供类小程序的标准&一致化的生产、开放、运营等能力,它有着多种业务形态,如商品卡片、权益卡片以及互动卡片等等,ISV开发的小部件可以以极低成本部署到店铺、详情、订阅等业务场景,极大提高了运营&分发效率。
从端上技术视角看,小部件首先是一个业务容器,它的特点是DSL标准化、跨平台渲染、跨场景流通:
- DSL标准化是指小部件完全兼容小程序的DSL(不仅仅是DSL,还包括原子API能力、生产链路等等),开发者不需要额外学习即可快速上手;
- 跨平台渲染顾名思义,小部件内核(基于weex2.0)通过类似flutter自绘的方案可以在Android、iOS等不同操作系统上渲染出完全一致的效果,开发者不需要关心兼容性问题;
- 最后跨场景流通是指小部件容器可以『嵌入』到多种技术栈的其他业务容器中,比如Native、WebView、小程序等等,以此做到对开发者屏蔽底层容器差异并达到一次开发,多处运行的效果。
无独有偶,Canvas 在小部件下的技术方案与小部件容器嵌入其他业务容器的技术方案居然有不少相似之处,那么下边笔者就从 Canvas 渲染方面展开来讲一讲。
原理揭秘
端侧整体技术架构
小部件技术侧的整体架构如下图所示,宏观看可分为 “壳” 与 “核” 两层。
“壳”即小部件容器,主要包括DSL、小部件JSFramework、原子API以及扩展模块比如Canvas。
“核”为小部件的内核,基于全新的weex2.0。在weex1.0中我们使用类RN的原生渲染方案,而到了weex2.0与时俱进升级到了类Flutter的自绘渲染方案,因此weex2.0承担了小部件JS执行、渲染、事件等核心职责,并细分为JS脚本引擎、Framework与渲染引擎三模块。JS引擎在Android侧使用轻量的QuickJS,iOS侧使用JavaScriptCore,并且支持通过JSI编写与脚本引擎无关的Bindings;Framework层提供了与浏览器一致的CSSOM和DOM能力,此外还有C++ MVVM框架以及一些WebAPI等等(Console、setTimeout、…);最后是内部称之为Unicorn的渲染引擎,主要提供布局、绘制、合成、光栅化等渲染相关能力,Framework与渲染引擎层均使用C++开发,并对平台进行了相关抽象,以便更好的支持跨平台。
值得一提的是,unicorn渲染引擎内置了PlatformView能力,它允许在weex渲染的Surface上嵌入另一Surface,该Surface的内容完全由PlatformView开发者提供,通过这种扩展能力,Camera、Video等组件得以低成本接入,Canvas也正是基于此能力将小程序下的Native Canvas(内部称之为FCanvas)快速迁移到小部件容器。
多视角看渲染流程
更多细节还可以参考笔者先前的文章《跨平台Web Canvas渲染引擎架构的设计与思考(内含实现方案)》
到了本文的重点,首先依然从宏观角度看下Canvas大体的渲染流程,请看下面图示,我们从右到左看。
对开发者而言,直接接触到的是Canvas API,包括w3c制定Canvas2D API以及khronos group制定的WebGL API,它们分别通过canvas.getContext(‘2d’)和 canvas.getContext(‘webgl’) 获得,这些JS API会通过JSBinding的方式绑定到Native C++的实现,2D基于Skia实现而WebGL则直接调用OpenGLES接口。图形API需要绑定平台窗体环境即Surface,在Android侧可以是SurfaceView或是TextureView。
再往左是小部件容器层。对weex而言,渲染合成的基本单位是LayerTree,它描述了页面层级结构并记录了每个节点绘制命令,Canvas就是这颗LayerTree中的一个Layer — PlatformViewLayer(此Layer定义了Canvas的位置及大小信息),LayerTree通过unicorn光栅化模块合成到weex的Surface上,最终weex和Canvas的Surface均参与Android渲染管线渲染并由SurfaceFlinger合成器光栅化到Display上显示。
以上是宏观的渲染链路,下边笔者试着从Canvas/Weex/Android平台等不同视角分别描绘下整个渲染流程。
暂无评论内容