概述
先来看一下网上有开发者绘制的渲染流程图。
这里目前的版本和这张图相比已经有了改变,比如 WXDomStatement
-> DOMActionContextImpl
,WXRenderStatement
-> RenderActionContextImpl
。
渲染的流程包括:
- 通过 transformer 将 .we 文件转为 Js Bundle
- JS framework 根据 Js Bundle 生成 Virtual Dom
- 通过 JS 引擎把渲染数据传给 Native 端
- Native 端执行渲染工作,首次渲染时,会将所有结点都交给 Native Render 渲染,在 UI 更新时,计算出最小 dif,让 Native 仅渲染发生改变的结点。
本文着重介绍2-4步骤的渲染工作。
渲染流程图
这个过程我们从 Demo 中的 WXSDKInstance.render()
说起,到 IWXRenderListener.onViewCreated()
回调调用结束。
在渲染执行之前,先注册了渲染监听器,渲染监听器,当渲染结束时,把生成的 RenderContainer
返回。
看一下流程图:
1 | ├── WXSDKInstance.registerRenderListener() |
解析 JS
这一过成比较简单,调用 WXSDKInstance.render()
方法把转换成的 JS 代码给 JS 引擎处理。
这里需要说明一下在 WXSDKManager.createInstance()
方法中,会调用 WXRenderManager.registerInstance
方法:
1 | public void registerInstance(WXSDKInstance instance) { |
这里会获取当前 WXSDKInstance
的 ID,并生成 RenderActionContextImpl
放入到 ConcurrentHashMap
中去。WXSDKInstance
的 ID 在 WXSDKManager
中生成,每个 WXSDKInstance
实例在上一个基础上加一。
1 | String generateInstanceId() { |
指令分发
WXDomModule 分发JS发出的指令
WXDomModule
是派发渲染指令的枢纽,提供了 callDomMethod() 和 postAction()方法来派发渲染指令。
先看一下在 WXDomModule.callDomMethod()
方法中对指令的处理。
1 | public Object callDomMethod(String method, JSONArray args, long... parseNanos) { |
这里可以处理的 Action 包括:
- CreateBodyAction
- UpdateAttributeAction
- UpdateStyleAction
- RemoveElementAction
- AddElementAction
- MoveElementAction
- AddEventAction
- RemoveEventAction
- CreateFinishAction
- RefreshFinishAction
- UpdateFinishAction
- ScrollToElementAction
- AddRuleAction:参考 官网说明
- GetComponentRectAction
- InvokeMethodAction
这里的大部分 Action 是既实现了 DOMAction
又实现了 RenderAction
接口的,这种 Action 会执行 WXDomModule.postAction(DOMAction action, boolean createContext)
方法,先在 WeeXDomThread 线程中执行构建 DOM 的操作。然后通过 DOMActionContextImpl.postRenderTask()
生成 RenderActionTask
,再后面的批处理操作中处理这些渲染动作。
如果是没有实现 DOMAction
接口的 Action,就执行 WXDomModule.postAction(RenderAction action)
,直接立即在 UI 线程中执行渲染操作。
WXDomHandler 处理构建客户端DOM的指令
WXDomHandler
处理 WXDomModule 发过来的操作指令,比如
- MsgType.WX_EXECUTE_ACTION:接受一下 Dom 指令:CreateBodyAction、AddElementAction、UpdateStyleAction、UpdateAttributeAction、CreateFinishAction、UpdateFinishAction
- MsgType.WX_DOM_BATCH:批处理前面的 Dom 操作,执行渲染动作。这个不是 WXDomModule 发过来的,在 WXDomHandler 这边生成的。2ms 执行一次批处理操作。
- MsgType.WX_DOM_UPDATE_STYLE:被弃用的方法,更新 style。其实在
MsgType.WX_EXECUTE_ACTION
是可以处理 JS 端发出的UpdateStyleAction
操作的了,这里保留是为了有些在 Java 侧直接调用的 UPDATE STYLE 操作。 - MsgType.WX_CONSUME_RENDER_TASKS
1 | public boolean handleMessage(Message msg) { |
再来看一下 WXDomManager.executeAction()
方法:
1 | public void executeAction(String instanceId, DOMAction action, boolean createContext) { |
构建客户端 DOM
这一节我们以处理 CreateBodyAction
为例来介绍一下渲染过程中构建客户端 DOM 的处理。
先来看一下 CreateBodyAction.addDomInternal()
方法。dom
参数是代表类似这样 json 字符串的一个对象。{"attr":{},"ref":"_root","style":{"alignItems":"center","height":800,"justifyContent":"center","width":750},"type":"div"}
1 | protected void addDomInternal(DOMActionContext context, JSONObject dom) { |
解析JSON:
1 | public static @Nullable WXDomObject parse(JSONObject json, WXSDKInstance wxsdkInstance, WXDomObject parentDomObject){ |
生成 WXComponent:
1 | protected WXComponent generateComponentTree(DOMActionContext context, WXDomObject dom, WXVContainer parent) { |
渲染
这一节我们以处理 CreateBodyAction
为例来介绍一下渲染过程中对构建客户端 DOM 的渲染处理。
渲染阶段的类和生成 Native 组件的类有些是一一对应的,比如:DOMActionContextImpl – RenderActionContextImpl、DOMAction – RenderAction 等。CreateBodyAction.executeRender()
:
1 | public void executeRender(RenderActionContext context) { |
生成 Host View:
其实就是生成对应的Android View的过程。
WXComponent.createViewImpl()
1 | protected void createViewImpl() { |
WXDiv.initComponentHostView()
:
1 | @Override |
至此,渲染流程介绍完毕。