UI绘制流程(底层走向)

2022-01-23  本文已影响0人  GoLearning轻松学
public final class ActivityThread extends ClientTransactionHandler {
    @Override
    public void handleResumeActivity(IBinder token, boolean finalStateRequest, boolean isForward,
            String reason) {
                    ViewManager wm = a.getWindowManager();
                    View decor = r.window.getDecorView();
                    wm.updateViewLayout(decor, l);
    }
}
public class Activity extends ContextThemeWrapper{
.......
final void attach(Context context, ActivityThread aThread){
......
 mWindow = new PhoneWindow(this, window, activityConfigCallback);
 mWindow.setWindowManager(
                   mWindow.setWindowManager(
                (WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
                mToken, mComponent.flattenToString(),
                (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
        if (mParent != null) {
            mWindow.setContainer(mParent.getWindow());
        }
        mWindowManager = mWindow.getWindowManager();
......
}
......
}
public final class WindowManagerImpl implements WindowManager {
    @Override
    public void updateViewLayout(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
        applyDefaultToken(params);
        mGlobal.updateViewLayout(view, params);
    }
}
public final class WindowManagerGlobal {
    public void updateViewLayout(View view, ViewGroup.LayoutParams params) {

        synchronized (mLock) {
            int index = findViewLocked(view, true);
            ViewRootImpl root = mRoots.get(index);
            mParams.remove(index);
            mParams.add(index, wparams);
            root.setLayoutParams(wparams, false);
        }
    }
}
public final class ViewRootImpl implements ViewParent{
    void setLayoutParams(WindowManager.LayoutParams attrs, boolean newView) {
            if (newView) {
                mSoftInputMode = attrs.softInputMode;
                requestLayout();
            }
        }
    }
    @Override
    public void requestLayout() {
        if (!mHandlingLayoutInLayoutRequest) {
            checkThread();
            mLayoutRequested = true;
            scheduleTraversals();
        }
    }
    void scheduleTraversals() {
    .....
            mChoreographer.postCallback(
                    Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
  ......
    }
   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;
            }
        }
    }
    private void performTraversals() {
   .....
                    
                 performMeasure(childWidthMeasureSpec, childHeightMeasureSpec)
.....
                 performLayout(lp, mWidth, mHeight);
....
                 performDraw();
......
    }

    private void performMeasure(int childWidthMeasureSpec, int childHeightMeasureSpec) {
...
            mView.measure(childWidthMeasureSpec, childHeightMeasureSpec);
     ...
    }
}
public class View{
.....
    public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
        .....
                // measure ourselves, this should set the measured dimension flag back
                onMeasure(widthMeasureSpec, heightMeasureSpec);
     ......
}

在onCreate之后,就会进入ActivityThread的handleResumeActivity,这时,会把DecorView跟activity进行绑定,绑定之后就到非常重要的代码,wm.updateViewLayout();这里的wm是生命东西?它是在attach的时候 ,给windowset进的WindowManage,再get出来赋给了Activity的mWindowManage,这里的updateViewLayout(),其实是调用了WindowImpl的update Layout,接着它调用了WindowManagerGlobal的updateViewLayout,然后到这里就会真正的调用ViewRootImpl来进行相关的root去update、去setLayoutParams,然后紧接着再这里requestLayout();然后调用scheduleTraversals();
总的流程是:ActivityThread.handleResumeActivity->WindowManagerGlobal.updateViewLayout->ViewRootImpl.setLayoutParams->ViewRootImpl.requestLayout->ViewRootImpl.scheduleTraversals
scheduleTraversals才是我们UI绘制的起点。
这里面接着里面是一个runnable,里面做了一件事doTraversal();再里面执行了performTraversals,再里面看到从performMeasure,然后到performLayout,然后到performDraw,它们都干了什么事情?我们从performMeasure来看,这里会调用 mView.measure,这里就真到了我们想看的UI,所以紧接着会调用UI里面的messure函数,在这里会触发onMeasure,这个onMeasure才会出现到我们的这个View、自定义View和我们UI的onMesure函数上,执行完onMeasure函数,随着这个performTraversal函数里面,执行完measure就到performLayout,performLayout就调用onLayout,onLayout之后就performDraw,而performDraw里面会调用onDraw函数,所以这样子下来它的整个流程就是我们认的UI刷新流程推断出onMeasure->onLayout->onDraw,所以,这才是UI绘制的流程。

UI绘制的流程总结图
上一篇 下一篇

猜你喜欢

热点阅读