weexAndroid开发经验谈Android开发

深入Weex系列(六)之Weex渲染流程分析

2017-10-31  本文已影响437人  未来的理想

1、前言

在前两篇文章中我们结合源码学习了Module、Component的注册、调用、回调等流程,相信大家一定收获颇多,对Weex的理解也一定愈加深入。

那么本篇文章我们分析Weex的渲染流程,来看一看我们写的Js文件是如何在Native端变成Android里View的。

2、Weex渲染过程

2.1 渲染触发点

渲染触发点

在Activity中我们开个某个Weex页面使用的是WXSDKInstance中的render方法,最终也是按照常规套路通过WXBridge调用Js继续处理。

备注:Js引擎处理后回调Native这一部分要复杂的多,我们拆分成几步来看。

2.2 渲染准备

Weex渲染准备
备注:这是渲染准备阶段,实际上和上一篇分析Component的调用准备是一样的;都是加一个任务保存到mNormalTasks。

2.2 渲染流程分析

Weex渲染流程分析

从上我们可以看出真实的渲染过程由WXDomHandler发起,关键方法在DOMActionContextImpl和WXComponent中(标出关键方法的地方);也经历了测量、布局、绘制、处理事件、设置数据等流程。

渲染流程非常重要,里面有很多关键步骤,下面我们一一分析;

2.3 calculateLayout

calculateLayout分析:

2.4 createView

    /**
    * create view
    */
    public final void createView() {
        mHost = initComponentHostView(mContext);
        if (mHost == null && !isVirtualComponent()) {
            //compatible
            initView();
        }
        if(mHost != null){
            mHost.setId(WXViewUtils.generateViewId());
            ComponentObserver observer;
            if ((observer = getInstance().getComponentObserver()) != null) {
              observer.onViewCreated(this, mHost);
            }
        }
        onHostViewInitialized(mHost);
  }

createView分析:

2.5 setLayout

setLayout流程
  /**
   * layout view
   */
    public final void setLayout(ImmutableDomObject domObject) {
    
        ......
        Spacing parentPadding = (nullParent?new Spacing():mParent.getDomObject().getPadding());
        Spacing parentBorder = (nullParent?new Spacing():mParent.getDomObject().getBorder());
        Spacing margin = mDomObj.getMargin();
        int realWidth = (int) mDomObj.getLayoutWidth();
        int realHeight = (int) mDomObj.getLayoutHeight();
        int realLeft = (int) (mDomObj.getLayoutX() - parentPadding.get(Spacing.LEFT) -
                              parentBorder.get(Spacing.LEFT));
        int realTop = (int) (mDomObj.getLayoutY() - parentPadding.get(Spacing.TOP) -
                             parentBorder.get(Spacing.TOP)) + siblingOffset;
        int realRight = (int) margin.get(Spacing.RIGHT);
        int realBottom = (int) margin.get(Spacing.BOTTOM);
        ......
        mAbsoluteY = (int) (nullParent?0:mParent.getAbsoluteY() + mDomObj.getLayoutY());
        mAbsoluteX = (int) (nullParent?0:mParent.getAbsoluteX() + mDomObj.getLayoutX());
        ......
        setComponentLayoutParams(realWidth, realHeight, realLeft, realTop, realRight, realBottom, rawOffset);
        ......
        
    }

setLayout分析:

2.6 addEvents

    public void addEvent(String type) {

        ......
        View view = getRealView();
        if (type.equals(Constants.Event.CLICK) && view != null) {
            addClickListener(mClickEventListener);
        } else if ((type.equals(Constants.Event.FOCUS) || type.equals(Constants.Event.BLUR))) {
            addFocusChangeListener(new WXComponent.OnFocusChangeListener() {
                public void onFocusChange(boolean hasFocus) {
                    Map<String, Object> params = new HashMap<>();
                    params.put("timeStamp", System.currentTimeMillis());
                    fireEvent(hasFocus ? Constants.Event.FOCUS : Constants.Event.BLUR, params);
                }
            });
        } else if (view != null &&
                needGestureDetector(type)) {
            if (view instanceof WXGestureObservable) {
                if (mGesture == null) {
                    mGesture = new WXGesture(this, mContext);
                    boolean isPreventMove = WXUtils.getBoolean(getDomObject().getAttrs().get(Constants.Name.PREVENT_MOVE_EVENT), false);
                    mGesture.setPreventMoveEvent(isPreventMove);
                }
                mGestureType.add(type);
                ((WXGestureObservable) view).registerGestureListener(mGesture);
            } else {
                WXLogUtils.e(view.getClass().getSimpleName() + " don't implement " +
                        "WXGestureObservable, so no gesture is supported.");
            }
        } else {
            Scrollable scroller = getParentScroller();
            if (type.equals(Constants.Event.APPEAR) && scroller != null) {
                scroller.bindAppearEvent(this);
            }
            if (type.equals(Constants.Event.DISAPPEAR) && scroller != null) {
                scroller.bindDisappearEvent(this);
            }
        }
    }

addEvents分析:

2.7 bindData

bindData逻辑

bindData:

3、渲染流程图

总结:

4、对比

下面我们对Weex的渲染和Android的渲染流程进行一下对比

5、总结

欢迎持续关注Weex源码分析项目:Weex-Analysis-Project

欢迎关注微信公众号:定期分享Java、Android干货!

欢迎关注
上一篇 下一篇

猜你喜欢

热点阅读