1, the preface

In the first two articles, we combined the source code to learn Module, Component registration, call, callback and other processes, I believe that we must harvest a lot, Weex understanding will also be more in-depth.

In this article, we will analyze the rendering process of Weex and have a look at how we write Js files in the Native end of Android View.

2. Weex rendering process

2.1 Render trigger points

In the Activity, we open a Weex page using the Render method in WXSDKInstance, and finally continue processing by calling Js via WXBridge as usual.

Note: the callback to Native after Js engine processing is much more complex, we break it down into several steps.

2.2 Rendering Preparation

Note: This is the render preparation phase, which is actually the same as the call preparation for the Component in the previous analysis; Both add a task and save it to mNormalTasks.

2.2 Rendering process analysis

From the above we can see that the actual rendering process is initiated by WXDomHandler. The key methods are in DOMActionContextImpl and WXComponent (where the key methods are marked). It also goes through the process of measuring, laying out, drawing, handling events, setting up data, etc.

The rendering process is very important, and there are many key steps in it.

2.3 calculateLayout

CalculateLayout analysis:

  • DOMActionContextImpl. CalculateLayout (), the implementation of the LayoutEngine. LayoutNodeImpl (), this step is true parsing, save the Js store layout; The layoutNodeImpl() method is 720 lines long and parses the FlexBox layout and saves the results to CSSLayout.

2.4 the 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); }Copy the code

CreateView analysis:

  • Create the target Component object and follow along to see the initComponentHostView method, which we must override for our custom Component;

2.5 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); . }Copy the code

SetLayout analysis:

  • SetLayout () gets the real width and height and the position of the four vertices, which is similar to Measure and Layout in native Android.
  • SetComponentLayoutParams () conversion of native recognition of LayoutParams, and will call setLayoutParams(), we know that this method will call the Measure, Layout, Draw and other processes of the native View;

2.5 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); }}}Copy the code

AddEvents analysis:

  • AddEvents () adds event handling to the View;

2.6 bindData

BindData:

  • Update Style, bind data, etc.
  • This is implemented in the updateProperties() method, where the implementation is a MethodInvoker reflection calling method;

3. Rendering flow chart

Conclusion:

  • The Weex rendering process is initiated by Native and transmitted to V8 engine through JsBridge. After processing, the instructions are sent back to Native.
  • Dom related operations are switched to Dom thread operations using WXDomHandler;
  • LayoutNodeImpl is the core measurement process that parses FlexBox layout, calculates Dom location information and stores it;
  • The WXRenderHandler then switches the subsequent worker thread to the RenderThread, the UI thread;
  • Component creates the concrete View;
  • SetLayout is actually a params that converts location information to native View recognition;
  • AddEvents addEvents;
  • BindData set style and assignment;

4, contrast

Here’s a comparison of Weex’s rendering process with Android’s:

  • For Android native rendering needs to go through Measure, Layout, Draw and other steps;
  • For Weex, the Android Native rendering process is all and only part of it, because we write Js code but the actual display is a Native control;
  • Weex has more processes than native: interacting with V8, parsing and generating Dom, setting properties and assigning values (extensions), etc.

5, summary

  • Weex rendering process analysis is much more difficult than Module, Component and other components, after all, Module and other components are only a Component and this is a complete process;
  • Weex rendering process analysis depends on the implementation of modules, components and other components, which is why I first analyze these two components;
  • In the Weex rendering process analysis, we first touched on Weex thread switching, which will be discussed later;
  • It is recommended that we actually track the Weex source code, which has a lot of details to learn;

Welcome to the Weex source code analysis project:Weex-Analysis-Project

Welcome to pay attention to wechat public number: regularly share Java, Android dry goods!