Activity的setContentView看View的绘制流程

来源:互联网 发布:死或生5优化 编辑:程序博客网 时间:2024/06/05 21:16

Activity 的setContentView看View的绘制流程

1.Activity.setContentView

    public void setContentView(@LayoutRes int layoutResID) {        //获取window = PhoneWindow对象        getWindow().setContentView(layoutResID);        initWindowDecorActionBar();    }

2.进入PhoneWindow.setContentView

    @Override    public void setContentView(int layoutResID) {        if (mContentParent == null) {            // 1.初始化DecorView对象,装在各种styleable属性            /**            //2.注入一个用于存子View的mContentRoot容器,再装入DecorView中,为什么这样做?            //我也不太明白,我猜是为了分离DecorView的部分业务吧            View in = mLayoutInflater.inflate(layoutResource, null);                    decor.addView(in, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));                    mContentRoot = (ViewGroup) in;            */            详见2.1            installDecor();        ... 省略N行 ...         详见2.2        mContentParent.requestApplyInsets();        final Callback cb = getCallback();        if (cb != null && !isDestroyed()) {            cb.onContentChanged();        }    }    2.1 mContentParent = installDecor();        mContentParent.addView(view, params);        //mContentRoot 被添加进decorView中,而DecorView是一个FrameLayout        View in = mLayoutInflater.inflate(layoutResource, null);                decor.addView(in, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));                mContentRoot = (ViewGroup) in;    2.2 mContentParent.requestApplyInsets();        //mContentParent是View,此时进入View的requestFitSystemWindows方法,View间接又调起了ViewRootImpl的

3.进入ViewRootImpl

    @Override    public void requestFitSystemWindows() {        checkThread();        mApplyInsetsRequested = true;        //准备View绘制流程工作        scheduleTraversals();    }    3.1        void scheduleTraversals() {        if (!mTraversalScheduled) {            mTraversalScheduled = true;            mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();            //mTraversalRunnable 是一个runnbale ,run方法执行了            mChoreographer.postCallback(                    Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);            if (!mUnbufferedInputDispatch) {                scheduleConsumeBatchedInput();            }            notifyRendererOfFramePending();            pokeDrawLockIfNeeded();        }    }    3.2 TraversalRunnable        final class TraversalRunnable implements Runnable {        @Override        public void run() {            //开始View绘制流程            doTraversal();        }    }

4.开始 performTraversals ,里面有7百多行代码

private void performTraversals() {        //1.处理LayoutParams相关        //2.处理mAttachInfo相关和相关attachedWindow回调分发和回调        //3.布置宽高        //4. performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);        //确认是否需要再次测量,如果在测量过程中,有子View强行不和measureSpec给的有冲突,那就调整再次测量。        //5.performLayout(lp, desiredWindowWidth, desiredWindowHeight);        //6.performDraw()        //7.如果中途有View改变的visibility,则调用前面的scheduleTraversals();重新走流程。    }

伟大的7百行代码,干了很多事情,真能干。从上面的代码可以找出我们View绘制流程中常见的三个方法 performMeasure,performLayout,performDraw ,这三个方法分别各自调用自己的分发过程。在这里就不分析了,网上一大把View的绘制流程。至此,一个Activity就这样降临到你眼前的眼帘,感谢看到这里的你,一边看源码一边敲的,做个粗略的笔记,如有遗漏,希望不吝纠正,感谢~

原创粉丝点击