一、weexSDK初始化流程

WXSDKEngine.initialize(Application application,InitConfig config);

//WXSDKEngine的init方法已经被弃用,weex的初始化需要使用下面这个initialize方法

public static void initialize(Application application,InitConfig config){

synchronized (mLock) {

//如果已经初始化过那么直接return

if (mIsInit) {

return;

}

long start = System.currentTimeMillis();

WXEnvironment.sSDKInitStart = start;

if(WXEnvironment.isApkDebugable()){

WXEnvironment.sLogLevel = LogLevel.DEBUG;

}else{

if(WXEnvironment.sApplication != null){

WXEnvironment.sLogLevel = LogLevel.WARN;

}else {

WXLogUtils.e(TAG,"WXEnvironment.sApplication is " + WXEnvironment.sApplication);

}

}

doInitInternal(application,config);

WXEnvironment.sSDKInitInvokeTime = System.currentTimeMillis()-start;

WXLogUtils.renderPerformanceLog("SDKInitInvokeTime", WXEnvironment.sSDKInitInvokeTime);

//监测weex表现的的一个检测器的初始化

WXPerformance.init();

mIsInit = true;

}

}
此方法最终会调用doInitInternal(application,config),其余部分的代码叔要是设置apk的debug和log模式,计算weexSDK初始化所需时间等。那么接下来看doInitInternal(application,config)的代码。

private static void doInitInternal(final Application application,final InitConfig config){

//这里给WXEnvironment中的application赋值,方便后续使用

WXEnvironment.sApplication = application;

if(application == null){//application为空的话报错

WXLogUtils.e(TAG, " doInitInternal application is null");

WXExceptionUtils.commitCriticalExceptionRT(null,

WXErrorCode.WX_KEY_EXCEPTION_SDK_INIT,

"doInitInternal",

WXErrorCode.WX_KEY_EXCEPTION_SDK_INIT.getErrorMsg() + "WXEnvironment sApplication is null",

null);

}

//weex环境初始化标识设置为false

WXEnvironment.JsFrameworkInit = false;

//通过单例模式获取一个WXBridgeManager的唯一实例,使用WXBridgeManager开启一个安全的线程初始化weex框架。

//开启安全线程的细节暂时不深究,这里主要看weex框架的初始化流程

WXBridgeManager.getInstance().post(new Runnable() {

@Override

public void run() {

//开始初始化时间

long start = System.currentTimeMillis();

//获取WXSDKManager实例

WXSDKManager sm = WXSDKManager.getInstance();

//使用sm监听weex框架初始化,我们可以通过WXSDKManager.registerStatisticsListener()

//注册一个监听器

sm.onSDKEngineInitialize();

//设置weex框架配置项

if(config != null ) {

sm.setInitConfig(config);

}

//初始化so文件加载器,后两个参数分别为初始化时的加载器和监听器。

WXSoInstallMgrSdk.init(application,

sm.getIWXSoLoaderAdapter(),

sm.getWXStatisticsListener());

//加载so库文件,如不设置自定义的IWXSoLoaderAdapter,那么采用系统默认方式加载

boolean isSoInitSuccess = WXSoInstallMgrSdk.initSo(V8_SO_NAME, 1, config!=null?config.getUtAdapter():null);

if (!isSoInitSuccess) {//加载失败报错

WXExceptionUtils.commitCriticalExceptionRT(null,

WXErrorCode.WX_KEY_EXCEPTION_SDK_INIT,

"doInitInternal",

WXErrorCode.WX_KEY_EXCEPTION_SDK_INIT.getErrorMsg() + "isSoInit false",

null);

return;

}

//使用WXSDKManager初始化jsFramwork,就是讲weexSdk中assets下的js文件拷贝到缓存目录中,使用so的native方法执行

sm.initScriptsFramework(config!=null?config.getFramework():null);

//计算初始化所用时间

WXEnvironment.sSDKInitExecuteTime = System.currentTimeMillis() - start;

WXLogUtils.renderPerformanceLog("SDKInitExecuteTime", WXEnvironment.sSDKInitExecuteTime);

}

});

//注册weexSDK内置的一系列Component和Module

register();

}
二、组件(Component)注册流程

按照weex官网的流程,首先我们会调用WXSDKEngine的registerComponent(String type, Class<? extends WXComponent> clazz)方法。

我们在WXSDKEngine源码中找到这个方法:

public static boolean registerComponent(String type, Class<? extends WXComponent> clazz) throws WXException {

return WXComponentRegistry.registerComponent(type, new SimpleComponentHolder(clazz),new HashMap<String, Object>());

}
我们发现该方法实际上是调用了WXComponentRegistry.registerComponent(xx,xx,xx)方法,我们先对SimpleComponentHolder留意,后续会用到。那么我们跟踪到WXComponentRegistry中查看registerComponent方法的实现。

public static synchronized boolean registerComponent(final String type, final IFComponentHolder holder, final Map<String, Object> componentInfo) throws WXException {

if (holder == null || TextUtils.isEmpty(type)) {

return false;

}

//execute task in js thread to make sure register order is same as the order invoke register method.

//在js线程执行这个注册组件的任务,以确保我们注册组件的顺序与调用注册方法的顺序一致。

WXBridgeManager.getInstance()

.post(new Runnable() {

@Override

public void run() {

try {

Map<String, Object> registerInfo = componentInfo;

if (registerInfo == null){

registerInfo = new HashMap<>();

}

//设置注册信息

registerInfo.put("type",type);

//holder是之前让大家留意的SimpleComponentHolder类

registerInfo.put("methods",holder.getMethods());

//生成原生组件映射

registerNativeComponent(type, holder);

//将组件注册信息传递到jsFramwork,生成js中解析vue中原生component是所需的Json映射

registerJSComponent(registerInfo);

//sComponentInfos是js解析需要使用的类,包含所有组件的注册信息

sComponentInfos.add(registerInfo);

} catch (WXException e) {

WXLogUtils.e("register component error:", e);

}

}

});

return true;

}
以上有几行代码需要在跟踪代码进一步分析:

1、holder.getMethods();

此处的holder对象即之前让大家留意的new SimpleComponentHolder(clazz),我们跟踪源码看一下这个方法的实现

public static Pair<Map<String,Invoker>,Map<String,Invoker>> getMethods(Class clz){

Map<String, Invoker> methods = new HashMap<>();

Map<String, Invoker> mInvokers = new HashMap<>();

Annotation[] annotations;

Annotation anno;

try {

for (Method method : clz.getMethods()) {

try {

annotations = method.getDeclaredAnnotations();

for (int i = 0, annotationsCount = annotations.length;

i < annotationsCount; ++i) {

anno = annotations[i];

if(anno == null){

continue;

}

if (anno instanceof WXComponentProp) {

String name = ((WXComponentProp) anno).name();

methods.put(name, new MethodInvoker(method,true));

break;

}else if(anno instanceof JSMethod){

JSMethod methodAnno = (JSMethod)anno;

String name = methodAnno.alias();

if(JSMethod.NOT_SET.equals(name)){

name = method.getName();

}

mInvokers.put(name, new MethodInvoker(method,methodAnno.uiThread()));

break;

}

}

} catch (ArrayIndexOutOfBoundsException | IncompatibleClassChangeError e) {

//ignore: getDeclaredAnnotations may throw this

}

}

}catch (IndexOutOfBoundsException e){

e.printStackTrace();

//ignore: getMethods may throw this

}

return new Pair<>(methods,mInvokers);

}
代码很简单,我们可以看出这个方法获取了要注册的Component的所有属性和方法,并把它们方法两个map集合中,最后将两个map封装成Pair返回。

时间上就是通过对WXComponent.Class对象的解析获取了其所有的属性和方法(通过WXComponentProp和JSMethod注解)。

获取成功后通过registerInfo.put("methods",holder.getMethods());将这些属性和方法信息放到组件的注册信息中。

2、registerNativeComponent(type, holder);

此方法属于用于生成原生组件的映射,用于对js文件的解析,我们同样来看一下此方法的实现。

//WXComponentRegistry.java

private static boolean registerNativeComponent(String type, IFComponentHolder holder) throws WXException {

try {

holder.loadIfNonLazy();

sTypeComponentMap.put(type, holder);

}catch (ArrayStoreException e){

e.printStackTrace();

//ignore: ArrayStoreException: java.lang.String cannot be stored in an array of type java.util.HashMap$HashMapEntry[]

}

return true;

}
 holder.loadIfNonLazy();这行代码调用了SimpleComponentHolder的loadIfNonLazy方法对holder进行了加载,实际上是将组件属性和方法信息保存在SimpleComponentHolder类型的对象holder中,之后将holder保存到sTypeComponentMap中,这是一个component组件的映射集合Map,它是一个静态变量。后续与sComponentInfos配合实现对js文件中component组件的解析(将编译成的Json对象映射解析成原生组件)。

loadIfNonLazy()方法实现如下,比较简单,不在详细说明,看注释即可。

//SimpleComponentHolder.java

@Override

public void loadIfNonLazy() {

//获取类中所有注解

Annotation[] annotations = mClz.getDeclaredAnnotations();

for (Annotation annotation :

annotations) {

if (annotation instanceof Component){

if(!((Component) annotation).lazyload() && mMethodInvokers == null){

//通过此方法获得组件类的方法和属性,并保存

generate();

}

return;

}

}

}

private synchronized void generate(){

if(WXEnvironment.isApkDebugable()) {

WXLogUtils.d(TAG, "Generate Component:" + mClz.getSimpleName());

}

//通过getMethods()方法获取属性和方法信息

Pair<Map<String, Invoker>, Map<String, Invoker>> methodPair = getMethods(mClz);

//保存属性和方法信息到自身

mPropertyInvokers = methodPair.first;

mMethodInvokers = methodPair.second;

}

3、registerJSComponent(registerInfo);

此方法用于将组件的属性和方法信息转换成对象的Json对象。

//WXComponentRegistry.java

private static boolean registerJSComponent(Map<String, Object> componentInfo) throws WXException {

ArrayList<Map<String, Object>> coms = new ArrayList<>();

coms.add(componentInfo);

WXSDKManager.getInstance().registerComponents(coms);

return true;

}
//WXSDKManager.java

public void registerComponents(List<Map<String, Object>> components) {

mBridgeManager.registerComponents(components);

}
最终调用的是WXBridgeManager的invokeRegisterComponents方法。实现如下,我们结合注释说明一下实现过程。

//WXBridgeManager.java

/**
* Registered component
*/

public void registerComponents(final List<Map<String, Object>> components) {

//js线程处理器或者组件的集合为空则之间返回

if (mJSHandler == null || components == null

|| components.size() == 0) {

return;

}

//在JsThred中进行组件注册

post(new Runnable() {

@Override

public void run() {

invokeRegisterComponents(components, mRegisterComponentFailList);

}

}, null);

}

//注册组件

private void invokeRegisterComponents(List<Map<String, Object>> components, List<Map<String, Object>> failReceiver) {

//failReceiver是一个注册失败的组件的集合

if (components == failReceiver) {

throw new RuntimeException("Fail receiver should not use source.");

}

//jsFramwork初始化未完成就将组件放入到注册失败的集合中

if (!isJSFrameworkInit()) {

WXLogUtils.e("[WXBridgeManager] invokeRegisterComponents: framework.js uninitialized.");

for (Map<String, Object> comp : components) {

failReceiver.add(comp);

}

return;

}

if (components == null) {

return;

}

//将通过组件的映射信息将其转化为Json

WXJSObject[] args = {new WXJSObject(WXJSObject.JSON,

WXJsonUtils.fromObjectToJSONString(components))};

try {

//通过调用WXBridge的native方法execJS(),调用main.js中的registerComponent方法注册组件

mWXBridge.execJS("", null, METHOD_REGISTER_COMPONENTS, args);

} catch (Throwable e) {

WXLogUtils.e("[WXBridgeManager] invokeRegisterComponents ", e);

WXExceptionUtils.commitCriticalExceptionRT(null,

WXErrorCode.WX_KEY_EXCEPTION_INVOKE_REGISTER_CONTENT_FAILED,

METHOD_REGISTER_COMPONENTS,

WXErrorCode.WX_KEY_EXCEPTION_INVOKE_REGISTER_CONTENT_FAILED.getErrorMsg()

+ args.toString()

+ WXLogUtils.getStackTrace(e),

null);

}

}

三、模块(Module)注册流程

下面是相关实现代码,只写一下简单的注释,模块注册流程与组件注册很类似,不再详细说明,感兴趣可以尝试自己阅读源码分析一下。

//WXSDKEngine

public static boolean registerModule(String moduleName, Class<? extends WXModule> moduleClass) throws WXException {

return registerModule(moduleName, moduleClass,false);

}

public static <T extends WXModule> boolean registerModule(String moduleName, Class<T> moduleClass,boolean global) throws WXException {

return moduleClass != null && registerModule(moduleName, new TypeModuleFactory<>(moduleClass), global);

}

public static <T extends WXModule> boolean registerModule(String moduleName, ModuleFactory factory, boolean global) throws WXException {

//在WXSDKEngine中最终调用WXModuleManager.registerModule(moduleName, factory,global)

return WXModuleManager.registerModule(moduleName, factory,global);

}
//WXModuleManager

/**
* Register module to JavaScript and Android
*/

public static boolean registerModule(final String moduleName, final ModuleFactory factory, final boolean global) throws WXException {

if (moduleName == null || factory == null) {

return false;

}

if (TextUtils.equals(moduleName, WXDomModule.WXDOM)) {

WXLogUtils.e("Cannot registered module with name 'dom'.");

return false;

}

try {

//这句代码不知道为啥写,因为后面执行了相同的代码,就是将持有Module类信息的TypeModuleFactory对象保存到sModuleFactoryMap中      //去。不知道是不是源码写错了,有高见的同学请赐教

sModuleFactoryMap.put(moduleName, new ModuleFactoryImpl(factory));

} catch (Throwable e) {

}

//execute task in js thread to make sure register order is same as the order invoke register method.

WXBridgeManager.getInstance()

.post(new Runnable() {

@Override

public void run() {

if (sModuleFactoryMap != null && sModuleFactoryMap.containsKey(moduleName)) {

WXLogUtils.w("WXComponentRegistry Duplicate the Module name: " + moduleName);

}

try {

//原生代码中注册module模块的类信息

registerNativeModule(moduleName, factory);

} catch (WXException e) {

WXLogUtils.e("registerNativeModule" + e);

}

if (global) {

try {

WXModule wxModule = factory.buildInstance();

wxModule.setModuleName(moduleName);

sGlobalModuleMap.put(moduleName, wxModule);

} catch (Exception e) {

WXLogUtils.e(moduleName + " class must have a default constructor without params. ", e);

}

}

registerJSModule(moduleName, factory);

}

});

return true;

}
//原生代码中注册module模块的类信息

static boolean registerNativeModule(String moduleName, ModuleFactory factory) throws WXException {

if (factory == null) {

return false;

}

try {

if (!sModuleFactoryMap.containsKey(moduleName) ) {

//将持有Module类信息的TypeModuleFactory对象保存到sModuleFactoryMap中去

sModuleFactoryMap.put(moduleName, new ModuleFactoryImpl(factory));

}

}catch (ArrayStoreException e){

e.printStackTrace();

//ignore:

//may throw this exception:

//java.lang.String cannot be stored in an array of type java.util.HashMap$HashMapEntry[]

WXLogUtils.e("[WXModuleManager] registerNativeModule Error moduleName:"  + moduleName + " Error:" + e.toString());

}

return true;

}

//在Js中注册module模块的方法和名称信息

static boolean registerJSModule(String moduleName, ModuleFactory factory) {

Map<String, Object> modules = new HashMap<>();

modules.put(moduleName, factory.getMethods());

WXSDKManager.getInstance().registerModules(modules);

return true;

}
//WXBridgeManager

private void invokeRegisterModules(Map<String, Object> modules, List<Map<String, Object>> failReceiver) {

if (modules == null || !isJSFrameworkInit()) {

if (!isJSFrameworkInit()) {

WXLogUtils.d("[WXinvokeRegisterModulesBridgeManager] invokeRegisterModules: framework.js uninitialized.");

}

failReceiver.add(modules);

return;

}

//将modules转换成WXJSObject

WXJSObject[] args = {new WXJSObject(WXJSObject.JSON,

WXJsonUtils.fromObjectToJSONString(modules))};

try {

//调用WXBrige的native方法在js中注册module

mWXBridge.execJS("", null, METHOD_REGISTER_MODULES, args);

try {

Iterator<String> iter = modules.keySet().iterator();

while (iter.hasNext()) {

String module = iter.next();

if (module != null) {

WXModuleManager.resetModuleState(module, true);

WXLogUtils.e("[WXBridgeManager]invokeRegisterModules METHOD_REGISTER_MODULES success module:" + module);

}

}

} catch (Throwable e) {

}

} catch (Throwable e) {

WXExceptionUtils.commitCriticalExceptionRT(null,

WXErrorCode.WX_KEY_EXCEPTION_INVOKE_REGISTER_MODULES,

"invokeRegisterModules", WXErrorCode.WX_KEY_EXCEPTION_INVOKE_REGISTER_MODULES.getErrorMsg() +

" \n " + e.getMessage() + modules.entrySet().toString(),

null );

WXLogUtils.e("[WXBridgeManager] invokeRegisterModules:", e);

}

}
---------------------

最新文章

  1. Halcon11与VS2010联合开发
  2. h5原生拖拽
  3. 使用虚幻引擎中的C++导论(四-内存管理与垃圾回收)(终)
  4. javascript学习之位置获取
  5. EasyUI扩展方法
  6. Cisco ASA 5505 Routing Between Two (Internal) VLANS
  7. 关联式容器(associative containers)
  8. C#中隐式类型本地变量var
  9. 2017-03-02学习心得之Java代码
  10. 每次用 selenium 操作浏览器都还原了 (比如没有浏览器历史记录)
  11. iOS崩溃日志ips文件解析
  12. Python 配置 selenium 模拟浏览器环境,带下载链接
  13. 32 bit 与 64 bit 程序(1)如何识别?
  14. Python 字典(Dictionary) values()方法
  15. php mysqli 的使用方法
  16. [Shell]Bash基本功能:历史命令 &amp; 别名 &amp; Bash快捷键
  17. Linux每日小技巧---统计服务器IP连接数
  18. MyBatis-Generator最佳实践
  19. 机器学习入门-集成算法(bagging, boosting, stacking)
  20. java 和 C 代码运行效率的比较(整理)

热门文章

  1. POJ 1260-Pearls(DP)
  2. BEGINNING SHAREPOINT&amp;#174; 2013 DEVELOPMENT 第12章节--SP 2013中远程Event Receivers
  3. 一个JS多个数组取交集算法
  4. Hadoop的学习前奏(二)——Hadoop集群的配置
  5. LeetCode 171. Excel Sheet Column Number (Excel 表格列数字)
  6. 修改this指向(bind、call 和 apply)
  7. vim入门级使用
  8. MySQL 字符编码问题详细解释
  9. 03、HelleBaiduMap
  10. nginx初相识