谈一谈ViewRootImpl的performTraversals的来源

如果略微的知道一点View的绘制流程,那么你也许会知道view重新绘制的发起点是在最最根部的ViewParent也就是ViewRootImpl的performTraversals。

那么这个方法到底是如何被调起来的呢。

首先你需要知道界面的强制重绘是View的requestLayout这个方法。无论是在ViewGroup中还是我们自定义的view,在需要刷新的界面的时候都会去调用这个方法,这个方法会让整个界面强制刷新。
我们来看一看View.java的requestLayout()方法

public void requestLayout() {
        if (mMeasureCache != null) mMeasureCache.clear();

        if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == null) {
            // Only trigger request-during-layout logic if this is the view requesting it,
            // not the views in its parent hierarchy
            ViewRootImpl viewRoot = getViewRootImpl();
            if (viewRoot != null && viewRoot.isInLayout()) {
                if (!viewRoot.requestLayoutDuringLayout(this)) {
                    return;
                }
            }
            mAttachInfo.mViewRequestingLayout = this;
        }

        mPrivateFlags |= PFLAG_FORCE_LAYOUT;
        mPrivateFlags |= PFLAG_INVALIDATED;

        if (mParent != null && !mParent.isLayoutRequested()) {
            mParent.requestLayout();
        }
        if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == this) {
            mAttachInfo.mViewRequestingLayout = null;
        }
    }

两个步骤,第一个是判断当前是否正在requestLayout,如果是则调用viewRoot.requestLayoutDuringLayout。
如果没有那么一步一步往上的去调用parent的requestLayout。那么你应该知道最顶端的parent就是ViewRootImpl。我们就直接去看它的requestLayout方法:

    @Override
    public void requestLayout() {
        //如果没有正在处理requestLayout的请求
        if (!mHandlingLayoutInLayoutRequest) {
            //线程检验
            checkThread();
            mLayoutRequested = true;
            scheduleTraversals();
        }
    }
    void scheduleTraversals() {
        if (!mTraversalScheduled) {
            mTraversalScheduled = true;
            //暂停了handler的后续消息处理,防止界面刷新的时候出现同步问题
            mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();
           //将runnable发送给handler执行
            mChoreographer.postCallback(
                    Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
            if (!mUnbufferedInputDispatch) {
                scheduleConsumeBatchedInput();
            }
            notifyRendererOfFramePending();
            pokeDrawLockIfNeeded();
        }
    }

其实看到这边基本上已经明了了,接下去我们估计也能猜得到到底是怎么回事儿了。

    final TraversalRunnable mTraversalRunnable = new TraversalRunnable();

    final class TraversalRunnable implements Runnable {
        @Override
        public void run() {
            doTraversal();
        }
    }

    void doTraversal() {
        if (mTraversalScheduled) {
            mTraversalScheduled = false;
            mHandler.getLooper().getQueue().removeSyncBarrier(mTraversalBarrier);

            if (mProfile) {
                Debug.startMethodTracing("ViewAncestor");
            }

            performTraversals();

            if (mProfile) {
                Debug.stopMethodTracing();
                mProfile = false;
            }
        }
    }

最终requestLayout是这样促成从最根部的ViewRootImpl开始进行measure,layout,draw往下分发。

你可能感兴趣的:(谈一谈ViewRootImpl的performTraversals的来源)