美文网首页Android进阶
View绘制流程(测量,摆放,绘制)

View绘制流程(测量,摆放,绘制)

作者: 天宇666 | 来源:发表于2019-01-02 11:58 被阅读0次

    \color{red}{View绘制流程(测量,摆放,绘制)}

    起点ActivityThread.handleLaunchActivity()

    一、ActivityThread.performLaunchActivity();

    通过反射方式,创建Activity 实例,

    
    \\新建Application实例。
    
    Applicationapp=r.packageInfo.makeApplication(false,mInstrumentation);
    
    \\执行
    
    mInstrumentation.callActivityOnCreate(activity,r.state,r.persistentState);
    
    \\继续调用
    
    activity.performCreate(icicle,persistentState);
    

    然后调用Activity的onCreate方法。

    再执行我们设置的setContentView操作。

    getWindow().setContentView(view,params);
    
    mWindow=newPhoneWindow(this);
    

    执行PhoneWindow的setContentview(), 先创建次顶层DecorView,每个activity都对应一个窗口window,这个窗口是PhoneWindow的实例,PhoneWindow对应的布局是DecorView,是一个FrameLayout,DecorView内部又分为两部分,一部分是ActionBar,另一部分是ContentParent,即activity在setContentView对应的布局。

    接着ContentParent载入传入的layoutResID

    mLayoutInflater.inflate(layoutResID,mContentParent);
    
    //接着会执行
    
    activity.performStart();
    
    //对应
    
    activity的onStart()
    
    

    二、ActivityThread.handleResumeActivity()

    执行完performLaunchActivity接着执行performResumeActivity(),执行

    
    activity.performResume()
    
    //对应
    
    activity的onResume()
    

    然后开始执行绘制工作

    WindowManagerImpl.java

    ViewManagerwm=a.getWindowManager();
    
    Viewdecor=r.window.getDecorView();
    
    wm.addView(decor,l);
    
    ///...
    
    wm.updateViewLayout(decor,l);
    
    wm=((WindowManagerImpl)wm).createLocalWindowManager(this);
    

    接着执行

    WindowManagerGlobal.addView(view,params,mDisplay,mParentWindow);
    
    //创建root
    
    root=newViewRootImpl(view.getContext(),display);
    
    //下一步
    
    root.setView(view,wparams,panelParentView);
    
    //下一步
    
    requestLayout();
    

    \color{red}{viewRootImpl是用于管理activity的view,其成员mView对应的就是activity的decorView,viewRootImpl设置decorView的方法是setView}

    checkThread();就在requestLayout执行。然后执行scheduleTraversals();

    然后通过回调的方式执行doTraversal(); 接着执行performTraversals()

    然后执行performMeasure()

    ViewRootImpl.performMeasure(childWidthMeasureSpec,childHeightMeasureSpec);
    
    //下一步,mView为FrameLayout
    
    mView.measure(childWidthMeasureSpec,childHeightMeasureSpec);
    
    //下一步
    
    FrameLayout.onMeasure(widthMeasureSpec,heightMeasureSpec);
    

    这时候FrameLayout遍历子view(如果子View是ViewGroup,则继续往下走)

    然后执行:

    FrameLayout.measureChildWithMargins(child,widthMeasureSpec,0,heightMeasureSpec,0);
    
     protected void measureChildWithMargins(View child,
                int parentWidthMeasureSpec, int widthUsed,
                int parentHeightMeasureSpec, int heightUsed) {
            final MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();
    
            final int childWidthMeasureSpec = getChildMeasureSpec(parentWidthMeasureSpec,
                    mPaddingLeft + mPaddingRight + lp.leftMargin + lp.rightMargin
                            + widthUsed, lp.width);
            final int childHeightMeasureSpec = getChildMeasureSpec(parentHeightMeasureSpec,
                    mPaddingTop + mPaddingBottom + lp.topMargin + lp.bottomMargin
                            + heightUsed, lp.height);
    
            child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
        }
    

    如图中,childWidthMeasureSpec和childHeightMeasureSpec是计算后,子view的宽和高的大小以及测量模式。

    \color{red}{这个模式需注意一个特殊的地方,就是当parent为AT_MOST的时候,即使子view设定为MATCH_PARENT,也会强制把子view的测量模式重置为AT_MOST。}

    然后调用

    
    child.measure(childWidthMeasureSpec,childHeightMeasureSpec);
    
    //接着调用子view的onMeasure(widthMeasureSpec,heightMeasureSpec);
    

    当子view计算完之后,parent(viewgroup)会根据子view的宽高计算自己的宽高,并设置自己的宽高。

    即整个绘制过程是由外层开始往里,外层测量模式对子view的测量有影响,一层层往里调用,先测量最里层的view,然后逐步往外层,外层根据子view的宽高测量并设置自己的宽高。

    \color{red}{参考示意图:}

    1544412578294_3.png

    这样,测量就结束了

    接下来,执行performLayout();

    performDraw()

    先画外层的背景色,然后调用view的draw方法,先调用子view的dispachDraw(ViewGroup)或者onDraw(View)方法,

    相关文章

      网友评论

        本文标题:View绘制流程(测量,摆放,绘制)

        本文链接:https://www.haomeiwen.com/subject/rlxzlqtx.html