zoukankan      html  css  js  c++  java
  • Weex框架源码分析(Android)(一)

    一、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() +

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

         null );



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

      }

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

  • 相关阅读:
    poj 3310(并查集判环,图的连通性,树上最长直径路径标记)
    poj 3308(最小点权覆盖、最小割)
    poj 3281(网络流+拆点)
    poj 3275(传递闭包)
    poj 3204(最小割)
    poj 3164(最小树形图)
    poj 2987(最大权闭合图+割边最少)
    poj 2455(二分+最大流)
    poj 2391(二分+最大流)
    poj 2135(最小费用最大流)
  • 原文地址:https://www.cnblogs.com/ly570/p/11007573.html
Copyright © 2011-2022 走看看