Weex Android SDK源码分析之界面渲染(下)

来源:互联网 发布:苹果电脑做java开发 编辑:程序博客网 时间:2024/04/29 08:54

前言

在你读本篇文章之前请确认您已经阅读 Weex Android SDK源码分析之界面渲染(上),否则建议您先阅读上篇文章有利于您更深刻的了解~

流程图

插图1

插图1

源码分析

回忆一下上篇文章的讲解,最终由WxBridgeManage调用WxBridge调用了so中native代码进行JS代码解析,那么解析完成之后是如何返回给Android代码的呢?so返回的是什么数据呢?数据时如何转换的呢?数据与最终的UI有什么关系呢?最终是如何转换成view的呢?如何传递到activity中的呢?
带着这些的疑问,我们开始今天得讲解~

一、WXBridge —> 解析JS回调Android code

    /**     * Js 使用此方法回调Android代码     * @param instanceId      * @param tasks 任务     * @param callback 下一个任务的ID     */    public void callNative(String instanceId, String tasks, String callback) {        WXBridgeManager.getInstance().callNative(instanceId, tasks, callback);    }

二、WXBridgeManager — > 分配渲染任务

    /**     * Dispatch the native task to be executed.     *     * @param instanceId {@link WXSDKInstance#mInstanceId}     * @param tasks      tasks to be executed     * @param callback   next tick id 下一个挂钩子ID,so执行需要的     */    void callNative(String instanceId, String tasks, String callback) {        if (TextUtils.isEmpty(tasks)) {            return;        }        if (WXEnvironment.isApkDebugable()) {            mLodBuilder.append("[WXBridgeManager] callNative >>>>             instanceId:").append(instanceId)                       .append(", tasks:")                       .append(tasks).append(", callback:").append(callback);            WXLogUtils.d(mLodBuilder.substring(0));            mLodBuilder.setLength(0);        }        JSONArray array = JSON.parseArray(tasks);        int size = array.size();        if (size > 0) {            try {                JSONObject task;                for (int i = 0; i < size; ++i) {                    task = (JSONObject) array.get(i);                    if (task != null && WXSDKManager.getInstance()                    .getSDKInstance(instanceId) != null) {                        WXModuleManager                        .callModuleMethod(instanceId, (String) task.get("module")                        , (String) task.get("method")                        ,(JSONArray) task.get("args"));                    }                }            } catch (Exception e) {            }        }        if (UNDEFINED.equals(callback)            || mDestroyedInstanceId.equals(instanceId)) {            return;        }        // get next tick        getNextTick(instanceId, callback);    }    // 获取下一个需要渲染的JS数据    private void getNextTick(final String instanceId, final String callback) {        addNextTickTask(instanceId, callback, "{}");        sendMessage(instanceId, WXJSBridgeMsgType.CALL_JS_BATCH);    }    // 添加渲染数据    private void addNextTickTask(String instanceId, Object... args) {        if (args == null || args.length == 0) {            return;        }        ArrayList<Object> argsList = new ArrayList<>();        for (Object arg : args) {            argsList.add(arg);        }        WXHashMap<String, Object> task = new WXHashMap<>();        task.put(WXConst.KEY_METHOD, METHOD_CALLBACK);        task.put(WXConst.KEY_ARGS, args);        if (mNextTickTasks.get(instanceId) == null) {            ArrayList<WXHashMap<String, Object>> list =             new ArrayList<WXHashMap<String, Object>>();            list.add(task);            mNextTickTasks.put(instanceId, list);        } else {            mNextTickTasks.get(instanceId).add(task);        }    }

三、WXModuleManager —> 回调module方法

// 执行module中的方法static boolean callModuleMethod(String instanceId, String moduleStr    , String methodStr, JSONArray args) {    final WXModule wxModule = findModule(instanceId, moduleStr, methodStr);    if (wxModule == null) {      return false;    }    wxModule.mWXSDKInstance =     WXSDKManager.getInstance().getSDKInstance(instanceId);    HashMap<String, Method> methodsMap = sGlobalModuleMethodMap.get(wxModule);    methodsMap = methodsMap ==     null ? sInstanceModuleMethodMap.get(wxModule) : methodsMap;    if (methodsMap == null) {      return false;    }    final Method moduleMethod = methodsMap.get(methodStr);    try {      Type[] paramClazzs = moduleMethod.getGenericParameterTypes();      final Object[] params = new Object[paramClazzs.length];      Object value;      Type paramClazz;      for (int i = 0; i < paramClazzs.length; i++) {        paramClazz = paramClazzs[i];        value = args.get(i);        if (paramClazz == JSONObject.class) {          params[i] = value;        } else {          String sValue;          if (value instanceof String) {            sValue = (String) value;          } else {            sValue = JSON.toJSONString(value);          }          if (paramClazz == int.class) {            params[i] = Integer.parseInt(sValue);          } else if (paramClazz == String.class) {            params[i] = sValue;          } else if (paramClazz == long.class) {            params[i] = Long.parseLong(sValue);          } else if (paramClazz == double.class) {            params[i] = Double.parseDouble(sValue);          } else if (paramClazz == float.class) {            params[i] = Float.parseFloat(sValue);          } else if (ParameterizedType.class.          isAssignableFrom(paramClazz.getClass())) {            params[i] = JSON.parseObject(sValue, paramClazz);          } else if (IWXObject.class.isAssignableFrom(paramClazz.getClass())) {            params[i] = JSON.parseObject(sValue, paramClazz);          } else {            params[i] = JSON.parseObject(sValue, paramClazz);          }        }      }      // *** 找到道注解的方法体,进行执行 ***       WXModuleAnno anno = moduleMethod.getAnnotation(WXModuleAnno.class);      if (anno.runOnUIThread()) {        WXSDKManager.getInstance().postOnUiThread(new Runnable() {          @Override          public void run() {            try {              // *** 执行module方法 ***              moduleMethod.invoke(wxModule, params);            } catch (Exception e) {           }          }        }, 0);      } else {        moduleMethod.invoke(wxModule, params);      }    } catch (Exception e) {      return false;    } finally {      if (wxModule instanceof WXDomModule) {        wxModule.mWXSDKInstance = null;      }    }    return true;  }  // 找到module 例如 WXDOMModule  private static WXModule findModule(String instanceId, String moduleStr, String methodStr) {    // find WXModule    WXModule wxModule = sGlobalModuleMap.get(moduleStr);    Class<? extends WXModule> moduleClass = sModuleClazzMap.get(moduleStr);    if (wxModule == null) {      HashMap<String, WXModule> moduleMap = sInstanceModuleMap.get(instanceId);      if (moduleMap == null) {        moduleMap = new HashMap<>();        sInstanceModuleMap.put(instanceId, moduleMap);      }      // if cannot find the Module, create a new Module and save it      wxModule = moduleMap.get(moduleStr);      if (wxModule == null) {        try {          wxModule = moduleClass.getConstructor().newInstance();        } catch (Exception e) {          return null;        }        moduleMap.put(moduleStr, wxModule);        // set instance        wxModule.mWXSDKInstance =         WXSDKManager.getInstance().getSDKInstance(instanceId);      }    }    // find module method    HashMap<String, Method> methodsMap = sGlobalModuleMethodMap.get(wxModule);    methodsMap = methodsMap == null ?     sInstanceModuleMethodMap.get(wxModule) : methodsMap;    if (methodsMap == null) {      methodsMap = getModuleMethods2Map(moduleClass);      sInstanceModuleMethodMap.put(wxModule, methodsMap);    }    return wxModule;  }

四、WXDomModule — > module 方法被触发

public final class WXDomModule extends WXModule {  /**   *  创建 Body UI   * @param element info about how to create a body   */  @WXModuleAnno(moduleMethod = true, runOnUIThread = false)  public void createBody(JSONObject element) {    if (element == null) {      return;    }    Message msg = Message.obtain();    WXDomTask task = new WXDomTask();    task.instanceId = mWXSDKInstance.getInstanceId();    task.args = new ArrayList<>();    task.args.add(element);    msg.what = WXDomHandler.MsgType.WX_DOM_CREATE_BODY;    msg.obj = task;    // *** 发送createBody消息 ***    WXSDKManager.getInstance().getWXDomManager().sendMessage(msg);  }}  

五、WXDomManager —> 发送createBody等消息

// 发送消息  createBody 或者 refresh等public void sendMessage(Message msg) {    if (msg == null || mDomHandler == null || mDomThread == null        || !mDomThread.isWXThreadAlive() || mDomThread.getLooper() == null) {      return;    }    mDomHandler.sendMessage(msg);  }

六、WXDomHandler — > 分发任务类型

// DOM 操作handlerclass WXDomHandler implements Handler.Callback {  /**   * The batch operation in dom thread will run at most once in 16ms.   */  private static final int DELAY_TIME = 16;//ms  private WXDomManager mWXDomManager;  private boolean mHasBatch = false;  public WXDomHandler(WXDomManager domManager) {    mWXDomManager = domManager;  }  @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:        // *** createBody ***        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));        break;      case MsgType.WX_DOM_ADD_DOM:        mWXDomManager.addDom(task.instanceId, (String) task.args.get(0),         (JSONObject) task.args.get(1), (Integer) task.args.get(2));        break;      case MsgType.WX_DOM_REMOVE_DOM:        mWXDomManager.removeDom(task.instanceId, (String) task.args.get(0));        break;      case MsgType.WX_DOM_MOVE_DOM:        mWXDomManager.moveDom(task.instanceId, (String) task.args.get(0), (String) task.args.get(1), (Integer) task.args.get(2));        break;      case MsgType.WX_DOM_ADD_EVENT:        mWXDomManager.addEvent(task.instanceId, (String) task.args.get(0),         (String) task.args.get(1));        break;      case MsgType.WX_DOM_REMOVE_EVENT:        mWXDomManager.removeEvent(task.instanceId,         (String) task.args.get(0), (String) task.args.get(1));        break;      case MsgType.WX_DOM_CREATE_FINISH:        mWXDomManager.createFinish(task.instanceId);        break;      case MsgType.WX_DOM_REFRESH_FINISH:        mWXDomManager.refreshFinish(task.instanceId);        break;      case MsgType.WX_DOM_BATCH:        mWXDomManager.batch();        mHasBatch = false;        break;      case MsgType.WX_DOM_SCROLLTO:        mWXDomManager.scrollToDom(task.instanceId,         (String) task.args.get(0), (JSONObject) task.args.get(1));        break;      default:        break;    }    return true;  }  public static class MsgType {    public static final int WX_DOM_CREATE_BODY = 0x0;    public static final int WX_DOM_UPDATE_ATTRS = 0x01;    public static final int WX_DOM_UPDATE_STYLE = 0x02;    public static final int WX_DOM_ADD_DOM = 0x03;    public static final int WX_DOM_REMOVE_DOM = 0x04;    public static final int WX_DOM_MOVE_DOM = 0x05;    public static final int WX_DOM_ADD_EVENT = 0x06;    public static final int WX_DOM_REMOVE_EVENT = 0x07;    public static final int WX_DOM_SCROLLTO = 0x08;    public static final int WX_DOM_CREATE_FINISH = 0x09;    public static final int WX_DOM_REFRESH_FINISH = 0x0a;    public static final int WX_DOM_BATCH = 0xff;  }}

七、WXDomManager — > DOM 管理

  /**   * Invoke {@link WXDomStatement} for creating body according to the JSONObject.   * @param instanceId   *  {@link com.taobao.weex.WXSDKInstance#mInstanceId} for the instance   * @param element the jsonObject according to which to create command object.   */  void createBody(String instanceId, JSONObject element) {    if (!isDomThread()) {      throw new WXRuntimeException      ("Create body operation must be done in dom thread");    }    // *** 调用DOM声明进行元素创建    WXDomStatement statement = new WXDomStatement(instanceId, mWXRenderManager);    mDomRegistries.put(instanceId, statement);    statement.createBody(element);  }

八、WXDomStatement — > DOM声明

  /**   * 创建根据JSONObject创造体命令对象,并且把命令对象添加到队列.    * @param element the jsonObject according to which to create command object.   */  void createBody(JSONObject element) {    if (mDestroy) {      return;    }    WXSDKInstance instance =     WXSDKManager.getInstance().getSDKInstance(mInstanceId);    if (element == null) {      if (instance != null) {        instance.commitUTStab(WXConst.DOM_MODULE,         WXErrorCode.WX_ERR_DOM_CREATEBODY);      }      return;    }    WXDomObject domObject = parseInner(element);    Map<String, Object> style = new HashMap<>(5);    if (domObject.style == null ||     !domObject.style.containsKey(WXDomPropConstant.WX_FLEXDIRECTION)) {      style.put(WXDomPropConstant.WX_FLEXDIRECTION, "column");    }    if (domObject.style == null ||     !domObject.style.containsKey(WXDomPropConstant.WX_BACKGROUNDCOLOR)) {      style.put(WXDomPropConstant.WX_BACKGROUNDCOLOR, "#ffffff");    }    //If there is height or width in JS, then that value will override value here.    if (domObject.style == null ||     !domObject.style.containsKey(WXDomPropConstant.WX_WIDTH)) {      style.put(WXDomPropConstant.WX_WIDTH,       WXViewUtils.getWebPxByWidth(WXViewUtils.getWeexWidth(mInstanceId)));    }    if (domObject.style == null ||     !domObject.style.containsKey(WXDomPropConstant.WX_HEIGHT)) {      style.put(WXDomPropConstant.WX_HEIGHT,       WXViewUtils.getWebPxByWidth(WXViewUtils.getWeexHeight(mInstanceId)));    }    domObject.ref = WXDomObject.ROOT;    domObject.updateStyle(style);    transformStyle(domObject, true);    final WXComponent component =     mWXRenderManager.createBodyOnDomThread(mInstanceId, domObject);    AddDomInfo addDomInfo = new AddDomInfo();    addDomInfo.component = component;    mAddDom.put(domObject.ref, addDomInfo);    mNormalTasks.add(new IWXRenderTask() {      @Override      public void execute() {        mWXRenderManager.createBody(mInstanceId, component);      }    });    mDirty = true;    mFlushes.add(domObject.ref);    if (instance != null) {      instance.commitUTStab(WXConst.DOM_MODULE, WXErrorCode.WX_SUCCESS);    }  }

九、WXRenderManager —-> DOM操作

public WXComponent createBodyOnDomThread(String instanceId, WXDomObject domObject) {        WXRenderStatement statement = mRegistries.get(instanceId);        if (statement == null) {            return null;        }        return statement.createBodyOnDomThread(domObject);    }

十、WXRenderStatement —> DOM对象转换组件

    WXComponent createBodyOnDomThread(WXDomObject dom) {        if (mWXSDKInstance == null) {            return null;        }        WXDomObject domObject = new WXDomObject();        domObject.type = WXBasicComponentType.DIV;        domObject.ref = "god";        mGodComponent = (WXVContainer) WXComponentFactory.        newInstance(mWXSDKInstance, domObject, null, mInstanceId);        mGodComponent.createView(null, -1);        if (mGodComponent == null) {            if (WXEnvironment.isApkDebugable()) {                WXLogUtils.e("rootView failed!");            }            //TODO error callback            return null;        }        FrameLayout frameLayout = (FrameLayout) mGodComponent.getView();        ViewGroup.LayoutParams layoutParams =         new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);        frameLayout.setLayoutParams(layoutParams);        frameLayout.setBackgroundColor(Color.TRANSPARENT);        WXComponent component = generateComponentTree(dom, mGodComponent);        mGodComponent.addChild(component);        mRegistry.put(component.getRef(), component);        return component;    }//  dom 对象转换 component treeprivate WXComponent generateComponentTree(WXDomObject dom, WXVContainer parent) {        if (dom == null || parent == null) {            return null;        }        WXComponent component = WXComponentFactory.newInstance(mWXSDKInstance, dom,        parent, mInstanceId, parent.isLazy());        mRegistry.put(dom.ref, component);        if (component instanceof WXVContainer) {            WXVContainer parentC = (WXVContainer) component;            int count = dom.childCount();            WXDomObject child = null;            for (int i = 0; i < count; ++i) {                child = dom.getChild(i);                if (child != null) {                    parentC.addChild(generateComponentTree(child, parentC));                }            }        }        return component;    }

十一、WXRenderManager— > WXComponent 转换

    // 得到Wx组件进行最终创建    public void createBody(String instanceId, WXComponent component) {        WXRenderStatement statement = mRegistries.get(instanceId);        if (statement == null) {            return;        }        statement.createBody(component);    }

十二、WXRenderStatement —> WX组件生成view

   /**     * 创建RootView;     * @see com.taobao.weex.dom.WXDomStatement#createBody(JSONObject)     */    void createBody(WXComponent component) {        long start = System.currentTimeMillis();        component.createView(mGodComponent, -1);        start = System.currentTimeMillis();        component.bind(null);        if (component instanceof WXScroller) {            WXScroller scroller = (WXScroller) component;            if (scroller.getView() instanceof ScrollView) {                mWXSDKInstance.setRootScrollView((ScrollView) scroller.getView());            }        }        // *** 创建成果rootview进行返回 ***         mWXSDKInstance.setRootView(mGodComponent.getRealView());        if (mWXSDKInstance.getRenderStrategy() != WXRenderStrategy.APPEND_ONCE) {            mWXSDKInstance.onViewCreated(mGodComponent);        }    }

十三、WXSDKInstance —> 接受view回调给activity

    public void onViewCreated(final WXComponent component) {    if (mRenderListener != null && mContext != null) {      runOnUiThread(new Runnable() {        @Override        public void run() {          if (mRenderListener != null && mContext != null) {            mRootCom = component;            mRenderListener.onViewCreated(WXSDKInstance.this, component.getView());          }        }      });    }  }

十四、IndexActivity —> 接受view绘制UI

    @Override    public void onViewCreated(WXSDKInstance wxsdkInstance, View view) {        Log.d("TAG", "onViewCreated");        if (flContainer != null) {            flContainer.addView(view);        }    }

结束语

 整个UI绘制流程就是这样的,猜测大家一定会掌握的,希望对大家有所帮助,谢谢您的观看!!!
4 0
原创粉丝点击