1、注册

IFComponentHolder

  1. public interface IFComponentHolder extends ComponentCreator,JavascriptInvokable {
  2. /**
  3. * 如果组件不是lazy加载模式,则优先加载此组件,默认是true
  4. * 解析组件类中的{@link com.taobao.weex.annotation.Component}注解
  5. * 接口触发时机在{@link WXComponentRegistry#registerNativeComponent}
  6. */
  7. void loadIfNonLazy();
  8. /**
  9. * 获取组件注册过程中保存的自定义属性创建的相关方法
  10. * 注册&生成入口流程参考 {@link JavascriptInvokable#getMethods()}
  11. * @param name
  12. * @return
  13. */
  14. Invoker getPropertyInvoker(String name);
  15. }

ComponentCreator

  1. public interface ComponentCreator {
  2. /**
  3. * 通过type创建对应的wx组件对象,调用的入口参见
  4. * {@link com.taobao.weex.ui.component.WXComponentFactory#newInstance(WXSDKInstance, WXVContainer, BasicComponentData)}
  5. */
  6. WXComponent createInstance(WXSDKInstance instance, WXVContainer parent, BasicComponentData basicComponentData) throws IllegalAccessException, InvocationTargetException, InstantiationException;
  7. }

JavascriptInvokable

  1. public interface JavascriptInvokable {
  2. /**
  3. * 首次调用的时机在{@link com.taobao.weex.ui.WXComponentRegistry#registerComponent}
  4. * `registerInfo.put("methods",holder.getMethods());`
  5. * 落地调用场景点{@link SimpleComponentHolder#getMethods(Class)} ()}
  6. * 作用是将注册的组件中带有如下两个组件的方法存起来
  7. * {@link com.taobao.weex.ui.component.WXComponentProp}
  8. * (注册组件属性的方法)
  9. * {@link com.taobao.weex.annotation.JSMethod}
  10. * (注册js调用的native方法)
  11. * 依次存放的实例(以 {@link SimpleComponentHolder} 为例,
  12. * 具体要看 {@link com.taobao.weex.ui.IFComponentHolder}的实现方法):
  13. * private Map<String, Invoker> mPropertyInvokers;
  14. * private Map<String, Invoker> mMethodInvokers;
  15. * {@link Invoker}是反射调用某个方法的接口,主要实现为{@link MethodInvoker}
  16. * @return 返回匹配的方法名字的数组
  17. */
  18. String[] getMethods();
  19. /**
  20. * 通过方法名字获取到在{@link #getMethods()}中保存的 mMethodInvokers
  21. * @param name 方法名字
  22. * @return 返回对应的 {@link MethodInvoker}
  23. */
  24. Invoker getMethodInvoker(String name);
  25. }

2、构建

由native js引擎解析完成后,开始以下调用链

  • WXBridge#callCreateBody

    • WXBridge#callCreateBody

    • action = new GraphicActionCreateBody()

        1. this.mComponentType = componentType;
        2. this.mStyle = style;
        3. this.mAttributes = attributes;
        4. this.mEvents = events;
        5. this.mMargins = margins;
        6. this.mPaddings = paddings;
        7. this.mBorders = borders;
      • mComponentType对应WXBasicComponentType中的常量

      • mStyle 对应 js中 <style scoped> 中定义的style,除了margin , padding样式

      • mEvents 对应 js中 标签的事件比如”@onclick”, “@appear”事件

      • mAttributes 对应js中 的属性,如”src”, “resize”等

        • basicComponentData = new BasicComponentData — 将上述的属性统统添加到bsd中

        • GraphicActionAbstractAddElement#createComponent — 创建WXComponent

          • ```java if (basicComponentData != null) { //添加解析出的属性到此Component Data中 basicComponentData.addStyle(mStyle); basicComponentData.addAttr(mAttributes); basicComponentData.addEvent(mEvents); basicComponentData.addShorthand(mMargins, CSSShorthand.TYPE.MARGIN); basicComponentData.addShorthand(mPaddings, CSSShorthand.TYPE.PADDING); basicComponentData.addShorthand(mBorders, CSSShorthand.TYPE.BORDER); }

      //通过basicComponentData实例化属性 WXComponent component = WXComponentFactory.newInstance(instance, parent, basicComponentData); //TODO 注册属性到WXRenderManager — 细节待摸清 WXSDKManager.getInstance().getWXRenderManager().registerComponent(getPageId(), getRef(), component);

      1. - WXComponentFactory#newInstance
      2. - ```java
      3. /**
      4. * 通过ComponentType去获取已经注册的IFComponentHolder
      5. * 注册的位置见 {@link WXSDKEngine#register()}
      6. */
      7. IFComponentHolder holder = WXComponentRegistry.getComponent(basicComponentData.mComponentType);
      8. if (holder == null) { // 没有注册的情况
      9. ...
      10. //没有注册的组件,默认当 CONTAINER,也就是一个 div标签 ->对应 WXFrameLayout
      11. holder = WXComponentRegistry.getComponent(WXBasicComponentType.CONTAINER);
      12. if (holder == null) { // 再挂了,就不管了
      13. ...
      14. return null;
      15. }
      16. }
         - WXRenderManager#registerComponent
      
            - ```java
      

      /**

      • 1、首先 {@link #mRenderContext}是一个线程安全的map,以instanceId为key,RenderContextImpl为value
      • {@link #mRenderContext} 的初始化发生在 {@link WXRenderManager}的构造函数中,而 {@link WXRenderManager}
      • 初始化是在 {@link WXSDKManager#WXSDKManager()} (Context)} 构造函数,并且是跟随父类都是唯一
      • 2、{@link #mRenderContext} 中的值数据添加的调用链. WXSDKInstance是在初始化模板的时候定义的(及构建时),
      • 实际的 {@link WXSDKInstance}存储在 {@link RenderContextImpl#RenderContextImpl}中的实例中,
      • RenderContextImpl和instanceId 以kv的形式保存在mWXRenderManager中
      • a.{@link WXSDKInstance#renderInternal(String, Script, Map, String, WXRenderStrategy)}
      • b.{@link WXSDKManager#createInstance(WXSDKInstance, Script, Map, String)}
      • c.{@link WXRenderManager#registerInstance(WXSDKInstance)}
      • @param instanceId 每一个实例都有一个instanceId 实例ID
      • @param ref 引用代表某个组件
      • @param comp 组件自身 */ public void registerComponent(String instanceId, String ref, WXComponent comp) { //已经在构建的时候保存了,一般不为null RenderContextImpl statement = mRenderContext.get(instanceId); if (statement != null) { //将组件comp和引用ref关联起来 statement.registerComponent(ref, comp); //理论上 WXSDKInstance 不为null if (null != statement.getInstance()){ //注册成功后,更新目前最大的组件数量 statement.getInstance().getApmForInstance().updateMaxStats(

         WXInstanceApm.KEY_PAGE_STATS_MAX_COMPONENT_NUM,
         statement.getComponentCount()
        

        ); } } }

        
             - component.addAnimationForElement(animationMap); --- 为组件添加动画
        
                - ```java
        //组件的id和动画为map
        animations.add(new Pair<>(getRef(),animMap));
        
    • WXRenderManager#postGraphicAction(..,action) -> action = GraphicActionCreateBody

      • 根据BasicGraphicAction的actionType来执行不同的处理方式

        • ```java if (action.mActionType == BasicGraphicAction.ActionTypeBatchEnd) { postAllStashedGraphicAction(instanceId,action); return; } else if (action.mActionType == BasicGraphicAction.ActionTypeBatchBegin || this.mBatchActions.size() > 0 ) { nativeBatchTimes ++ ; if (nativeBatchTimes > MAX_DROP_FRAME_NATIVE_BATCH) { postAllStashedGraphicAction(instanceId,action); } else { HashMap item = new HashMap<>(1); item.put(sKeyAction, action); mBatchActions.add(item); return; } }

      //默认执行这里, 将action信息post到主线程中 mWXRenderHandler.post(instanceId, action);

      
       - BasicGraphicAction.ActionTypeNormal 普通模式
      
          - mWXRenderHandler.post(instanceId, action) -- post主线程执行runnable
      
          - BasicGraphicAction#run -- 经过此回调中转操作到executeAction
      
          - GraphicActionCreateBody#executeAction
      
             - ```java
      try {
       //创建组件的View
       component.createView();
       //设置view显示的布局方式,以及绑定事件
       component.applyLayoutAndEvent(component);
       //绑定相关的style属性,attr属性等
       component.bindData(component);
       WXSDKInstance instance = getWXSDKIntance();
      
       if (component instanceof WXScroller) {
         WXScroller scroller = (WXScroller) component;
         if (scroller.getInnerView() instanceof ScrollView) {
             //对scroll view 单独处理,添加监听等
           instance.setRootScrollView((ScrollView) scroller.getInnerView());
         }
       }
      
       //将创建的view添加到mRenderContainer,并且重新设置mRenderContainer的显示区域大小
       instance.onRootCreated(component);
      
       //渲染策略 不是"一次添加",默认是 APPEND_ASYNC 就有对应的监听回调 mRenderListener.onViewCreated
       if (instance.getRenderStrategy() != WXRenderStrategy.APPEND_ONCE) {
         instance.onCreateFinish();
       }
      } catch (Exception e) {
       WXLogUtils.e("create body failed.", e);
      }
      
         - component.createView() -> WxComponent#createViewImpl
      
            - ```java
      

      if (mContext != null) { //通过子类创建View mHost = initComponentHostView(mContext); … if (mHost != null) {

       //创建的View没有id,则为其生成一个id
      

      if(mHost.getId() == View.NO_ID)

       mHost.setId(WXViewUtils.generateViewId());
      

      if(TextUtils.isEmpty(mHost.getContentDescription()) && WXEnvironment.isApkDebugable()){

       mHost.setContentDescription(getRef());
      

      } ComponentObserver observer; if ((observer = getInstance().getComponentObserver()) != null) {

       observer.onViewCreated(this, mHost);
      

      } } onHostViewInitialized(mHost);//host view相关的初始化 } else { WXLogUtils.e(“createViewImpl”, “Context is null”); }

      
                - WxComponent#onHostViewInitialized
      
                   - ```java
      protected void onHostViewInitialized(T host) {
       //一般初始化的时候,mAnimationHolder都为null,在此不会被执行,有在onLayout改变的时候执行动画
      if (mAnimationHolder != null) { //初始化后执行动画
       mAnimationHolder.execute(mInstance, this);
      }
      //:active 事件由 onTouch来处理,用于更新style相关
      setActiveTouchListener();
      }
      
         - component.applyLayoutAndEvent(component)
      
            - setLayout -- 处理view的显示方式
      
               - ```java
      

      setLayoutSize(component.getLayoutSize()); setLayoutPosition(component.getLayoutPosition()); setPaddings(component.getPadding()); setMargins(component.getMargin()); setBorders(component.getBorder());

      
                - parseAnimation -- 解析transformOrigin(类同pivot)和transform(真实动画表达式)中的各个表达式,创建PropertyValuesHolder与之对应(WXAnimaitonBean负责做动画相关的事)
      
                   - ```java
      for (final Pair<String, Map<String, Object>> pair : animations) {
       if (!TextUtils.isEmpty(pair.first)) {
         final WXAnimationBean animationBean = createAnimationBean(pair.first, pair.second);
         if (animationBean != null) {
             //创建动画执行的action
           GraphicActionAnimation action = new GraphicActionAnimation(getInstance(), getRef(), animationBean);
           //直接执行
           action.executeAction();
         }
       }
      }
      
            - GraphicActionAnimation#executeAction -- 设置interceptor开始执行动画
      
         - component.bindData(component)
      
            - ```java
      

      //1、背景样式用BorderDrawable //2、反射调用由WXComponentProp注解的方法 updateStyles(component); //设置背景颜色,border颜色,radius,border厚度 updateAttrs(component); //额外的数据设置,现在只有WxText在用 updateExtra(component.getExtra());

      
             - instance.onRootCreated(component)
      
                - ```java
      this.mRootComp = root;
      this.mRootComp.mDeepInComponentTree =1;//默认view的层级只有一层
       //将创建的component添加到根view
      mRenderContainer.addView(root.getHostView());
      //设置布局大小. layoutParams
      setSize(mRenderContainer.getWidth(),mRenderContainer.getHeight());
      
      • BasicGraphicAction.ActionTypeBatchBegin 批操作开始 — 未见使用场景

      • BasicGraphicAction.ActionTypeBatchEnd 批操作结束 — 未见使用场景