Weex渲染机制
1.讲什么
这篇文章主要简单介绍weex的渲染机制,将重点放在V8引擎在解析完.js文件后,客户端这边如何反序列化生成各种组件,最后组成界面的过程。
如上图,是一张网络普传的Weex工作原理图。介绍一下工作机制:
1. 首先通过编写.vue文件,完成界面组件设计以及逻辑代码编写;
2. Transformer :转换的意思,我们会借助Weex-Toolkit这个工具将.vue文件转换成.js文件
Weex-Toolkit
==$weex compile your_best_weex.[we or vue] . ==
3.deploy:意味着将这个.js文件上传到服务器,后面可以通过CMS下发到客户端
4.客户端收到后,由JS Framework处理,对IOS和Android,会通过V8引擎解析,以json的形式返回给客户端
5.客户端最后根据json完成自己的渲染
本文着墨在最后两步,重点放在最后一步,如何渲染成本地native组件。
2.时序图
先放出时序图,后面的步骤大家可以跟踪时序图走,方便对着看交互顺序。
这个时序图是按照从客户端一个Activity主动发起渲染请求开始,注册了RenderListener监听器,然后等待Weex框架处理完,在回调的时候从监听处获取成品view。Activity可以执行setContentView(view)添加到自己容器内。
结合时序图,先介绍整体的一个流程:
1. Activity发起渲染请求,参数带上渲染的js文件
2. Weex 接收到请求,完成初始化后,将js内容传到JS 引擎
3. 由JS 引擎完成 V DOM的操作,之后将V DOM对应的json字串回传给Weex
4. Weex 解析json,parse成一个个WxDomObject,然后创建对应的WxComponent,创建渲染任务
5. WxRenderManager具体处理渲染任务,渲染完成后,通知Activity渲染结果,完毕
这边首先需要介绍一下相关类的作用以及类之间的结构关系。Weex框架主要包括三大部分。主体是WXSDKManager,以组合的形式带上WXBridgeManager、WXRendermanager和WXDomManager。三个管理类如名称一样,负责各自的功能区域。WXBridgeManager主要负责 和 JS 引擎交互 ,发送native端java的请求到jni层,接收js引擎处理后从jni上返回的消息。WxDomManager负责构建客户端的dom结构,在WXBridgeManager接收到消息后,会交给WxDomManager处理,WxDomManager根据消息创建自己的Dom结构,添加、删除、修改元素。然后将对应的Dom的节点渲染成组件,这一步渲染的工作就需要WXRendermanager负责。当然,三者的管理类并不直接交互,管理类下面还有对应的功能类负责具体的通信、数据处理和管理。
下面会按照请求步骤,解读整个步骤。
客户端发送WXSDKInstance.render()请求后,会走重载然后调用自身方法:renderInternal():
private void renderInternal(String pageName, String template, Map<String, Object> options, String jsonInitData, WXRenderStrategy flag){
//......省略代码
/**
* 初始化容器
*/
ensureRenderArchor();
//......省略代码
/**
* 通知WXSDKManager进行渲染
*/
WXSDKManager.getInstance().createInstance(this, template, renderOptions, jsonInitData);
mRendered = true;
}
上面主要两件事情,第一ensureRenderArchor()做了初始化容器mRenderContainer的工作,WXSDKInstance有个比较重要的属性mRenderContainer,代表的是渲染完成后的根view,最后渲染完成后回调的也是这个view;之后就调用createInstance()。
WXSDKInstance作用其实相当于activity页面的代理,负责和页面进行交互。
void createInstance(WXSDKInstance instance, String code, Map<String, Object> options, String jsonInitData) {
/**
* 1.通知mWXRenderManager注册这个WXSDKInstance实例
* 2.通知mBridgeManager去解析这个js文件
*/
mWXRenderManager.registerInstance(instance);
mBridgeManager.createInstance(instance.getInstanceId(), code, options, jsonInitData);
}
public void registerInstance(WXSDKInstance instance) {
/**
* mRegistries以key,value的形式保存WXSDKInstance,对应的WXRenderStatement
* 这个WXRenderStatement作用是保存WXSDKInstance对应的所有的组件
*/
mRegistries.put(instance.getInstanceId(), new WXRenderStatement(instance));
}
代码比较简单,说明一下mRegistries是一个map,以WXSDKInstance的id和WXSDKInstance对应的WXRenderStatement作为key,value。而WXRenderStatement里面也有一个map,用来存放这个WXSDKInstance对应的所有组件
class WXRenderStatement {
private Map<String, WXComponent> mRegistry;
private WXSDKInstance mWXSDKInstance;
}
接回上面mBridgeManager.createInstance(),看看到底发生了什么事情:
public void createInstance(final String instanceId, final String template, final Map<String, Object> options, final String data) {
final WXSDKInstance instance = WXSDKManager.getInstance().getSDKInstance(instanceId);
WXModuleManager.createDomModule(instance);
post(new Runnable() {
@Override
public void run() {
invokeCreateInstance(instance, template, options, data);
}
}, instanceId);
}
主要还是两件事情,第一,为我们的WXSDKInstance创建了一个对象WxDomModule,这个WxDomModule的工作相当于一个跑腿,WXBridgeManager和JS 引擎交互得到的消息会交给WxDomModule传递到WXModuleManager。之后post了一个invokeCreateInstance()方法,这个方法执行在工作线程
private void invokeCreateInstance(@NonNull WXSDKInstance instance, String template, Map<