WeexSDK 初始化源码分析
整个Weex SDK 初始化过程,入口是WXSDKEngine.initialize(),方法主要是依靠 doInitInternal() 方法执行初始化操作。里面涉及了WXEnvironment 相关环境的设置,几个重要的Manager的初始化操作,包括WXBridgeManager、WXSDKManager、WXRenderManager、WXDomManager,前两个 manager 以单例形式呈现的。
初始化完相关管理类,后面进行 component、module的注册。
下面对这一过程,进行一一分析:
WXSDKEngine.doInitInternal() 方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| private static void doInitInternal(final Application application, final InitConfig config) { WXEnvironment.sApplication = application; WXEnvironment.JsFrameworkInit = false; WXBridgeManager.getInstance().post(new Runnable() { @Override public void run() { long start = System.currentTimeMillis(); WXSDKManager sm = WXSDKManager.getInstance(); if (config != null) { sm.setInitConfig(config); if (config.getDebugAdapter() != null) { config.getDebugAdapter().initDebug(application); } } WXSoInstallMgrSdk.init(application); boolean isSoInitSuccess = WXSoInstallMgrSdk.initSo(V8_SO_NAME, 1, config != null ? config.getUtAdapter() : null); if (!isSoInitSuccess) { return; } sm.initScriptsFramework(config != null ? config.getFramework() : null); WXEnvironment.sSDKInitExecuteTime = System.currentTimeMillis() - start; WXLogUtils.renderPerformanceLog("SDKInitExecuteTime", WXEnvironment.sSDKInitExecuteTime); } }); register(); }
|
WXSDKManager的初始化
首先,是WXSDKManager的初始化,会将WXRenderManager、WXDomManager初始化,并拿到WXBridgeManager实例的引用。
- 关于 WXRenderManager
管理渲染操作,主要操作管理的是WXRenderStatement对象(WXRenderManager 也并不是一个线程安全的类,涉及到UI的更新操作。后面会对WXRenderStatement 进行分析)
WXRenderManager 主要的2个成员:mRegistries 和 mWXRenderHandler:1 2
| private ConcurrentHashMap<String, WXRenderStatement> mRegistries; private WXRenderHandler mWXRenderHandler;
|
mRegistries存储WXRenderStatement,以 WXSDKInstance.id 为key存储WXRenderStatement,所以一个WXSDKInstance对应一个WXRenderStatement。
WXRenderManager 的 createBody、addComponent等等操作都是针对某个WXSDKInstance的 statement 调用操作的。具体的渲染,WXRenderStatement负责完成。
mWXRenderHandler 是将外界传给它的 渲染相关的task 发送消息,然后主线程收到messge后,进行相关渲染操作。
- 关于 WXDomManager
管理dom操作,作为客户端执行dom命令,会调用 WXDomStatement 创建命令执行相对应的操作。里面提供的方法通常是在 dom 线程中调用。
其中有:1 2 3 4 5
| private WXThread mDomThread; Handler mDomHandler; private WXRenderManager mWXRenderManager; private ConcurrentHashMap<String, WXDomStatement> mDomRegistries;
|
mDomRegistries 和上面类似,大家一看就懂,。
mWXRenderManager 是拿到上一步初始化好的 mWXRenderManager实例。
mDomThread是WXDomManager创建的一个thread,也是WXThread,其中的handler是WXDomHandler
mDomHandler 是这个mDomThread的handler引用。
WXDomHandler 是关于dom操作的一个类,实现了Handler.Callback接口,会将mDomHandler发送的dom消息分类处理,这一任务是交给了 WXDomManager:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| @Override public boolean handleMessage(Message msg) { if (msg == null) { return false; } int what = msg.what; Object obj = msg.obj; WXDomTask task = null; if (obj instanceof WXDomTask) { task = (WXDomTask) obj; } if (!mHasBatch) { mHasBatch = true; mWXDomManager.sendEmptyMessageDelayed(WXDomHandler.MsgType.WX_DOM_BATCH, DELAY_TIME); } switch (what) { case MsgType.WX_DOM_CREATE_BODY: mWXDomManager.createBody(task.instanceId, (JSONObject) task.args.get(0)); break; case MsgType.WX_DOM_UPDATE_ATTRS: mWXDomManager.updateAttrs(task.instanceId, (String) task.args.get(0), (JSONObject) task.args.get(1)); break; case MsgType.WX_DOM_UPDATE_STYLE: mWXDomManager.updateStyle( task.instanceId, (String) task.args.get(0), (JSONObject) task.args.get(1), task.args.size() > 2 && (boolean) task.args.get(2) ); break; case ... case ...
|
具体的manager操作,会交给对应的 domstatement 操作,上面已经说过。
WXSoInstallMgrSdk 是管理 so 相关操作和cpu平台的支持情况。
WXSoInstallMgrSdk.initSo() 执行 weexv8.so 包的加载,就和普通加载so包的方式一样(System.loadLibrary(libName) )。
这里注意:weex 的 so 包不支持 mips平台的
如果so包加载失败,则初始化操作会就此结束,后续工作不再执行。
so包加载完成之后,WXSDKManager会调用WXBridgeManager执行 js Framework的初始化,并发送消息给
WXBridgeManager,WXBridgeManager调用自己的 handleMessage() 处理操作,下面会有分析。
WXBridgeManager 的初始化
其次,WXBridgeManager 的初始化。会创建名为:WeexJSBridgeThread的 WXThread,WXThread是一个weex封装的HandlerThread。为了方便该线程的消息处理,具体细节可参考源码查看。WXBridgeManager 自己也实现了 Handler.Callback 接口,用于处理消息,接受消息后对 js framework 的初始化操作进行控制。
发送消息:
1 2 3 4 5 6 7 8 9 10 11
| * Initialize JavaScript framework * @param framework String representation of the framework to be init. */ public synchronized void initScriptsFramework(String framework) { Message msg = mJSHandler.obtainMessage(); msg.obj = framework; msg.what = WXJSBridgeMsgType.INIT_FRAMEWORK; msg.setTarget(mJSHandler); msg.sendToTarget(); }
|
接收消息:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| @Override public boolean handleMessage(Message msg) { if (msg == null) { return false; } int what = msg.what; switch (what) { case WXJSBridgeMsgType.INIT_FRAMEWORK: invokeInitFramework(msg); break; case WXJSBridgeMsgType.CALL_JS_BATCH: invokeCallJSBatch(msg); break; case ...
|
在 WXBridge 中,是调用 底层native的方法:
1 2 3 4 5 6
| * Init JSFrameWork * * @param framework assets/main.js */ public native int initFramework(String framework, WXParams params);
|
底层 C++代码中:
1 2 3
| jint Java_com_taobao_weex_bridge_WXBridge_initFramework(JNIEnv *env, jobject object, jstring script, jobject params)
|
js framework 初始化就交给 C++ 来处理了
在这里再多看一眼:在so包加载后,C++层第一步就会把 WXBridge 加载出来,作为2层之间的桥梁:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| * This function will be call when the library first be load. * You can do some init in the lib. return which version jni it support. */ jint JNI_OnLoad(JavaVM *vm, void *reserved) { LOGD("begin JNI_OnLoad"); JNIEnv *env; if ((vm)->GetEnv((void **) &env, JNI_VERSION_1_4) != JNI_OK) { return JNI_FALSE; } sVm = vm; jclass tempClass = env->FindClass( "com/taobao/weex/bridge/WXBridge"); jBridgeClazz = (jclass) env->NewGlobalRef(tempClass); env->DeleteLocalRef(tempClass); LOGD("end JNI_OnLoad"); return JNI_VERSION_1_4; }
|
注册操作
weex 内置的 component 和 module 都会在此过程中注册,这一过程还包含了dom的注册操作。
注册操作,会由registerModules来进行操作:registerModules(),registerComponents(),这两个都是异步执行,最终调用:
1 2 3 4 5 6 7 8
| WXJSObject[] args = {new WXJSObject(WXJSObject.JSON, WXJsonUtils.fromObjectToJSONString(modules))}; mWXBridge.execJS("", null, METHOD_REGISTER_MODULES, args); WXJSObject[] args = {new WXJSObject(WXJSObject.JSON, WXJsonUtils.fromObjectToJSONString(components))}; mWXBridge.execJS("", null, METHOD_REGISTER_COMPONENTS, args);
|
execJS() 最终是调用WXBridge.execJS() 的native方法,交给底层c++来执行:
1 2 3
| jint Java_com_taobao_weex_bridge_WXBridge_execJS(JNIEnv *env, jobject this1, jstring jinstanceid, jstring jnamespace, jstring jfunction, jobjectArray jargs)
|
C++ 使用反射的方式,找到WXJSObject类,找到相关的属性和方法,
1
| jclass jsObjectClazz = env->FindClass("com/taobao/weex/bridge/WXJSObject");
|
调用 js Framework的相关api 执行。
源码:
https://github.com/apache/incubator-weex/tree/master/android/sdk
https://github.com/alibaba/weex_v8core