View的measure, layout, draw整个过程

布局文件

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
</RelativeLayout>

布局文件Tree view图

ps:这边打开hierarchy viewer一直无法刷新到tree view图,直接用了孙群博客里面的图
这里写图片描述

measure过程

view在measure过程中涉及的方法:
public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
...//省略代码
onMeasure();
}
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
                getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
    }
viewGroup在measure过程中涉及的方法:
protected void measureChild(View child, int parentWidthMeasureSpec,
            int parentHeightMeasureSpec) {
        ...//省略代码
        child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
    }
protected void measureChildWithMargins(View child,
            int parentWidthMeasureSpec, int widthUsed,
            int parentHeightMeasureSpec, int heightUsed) {
        ...//省略代码
        child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
    }
measure过程分析:
1.View的measure()是final的,所以其子类不可以重写该方法。
2.View的measure()里面有调用onMeasure()方法,而且onMeasure()不是空方法,即有实现测量过程。子类若
想用自己的测量方式可以重写该方法。ps:一般都会重写onMeasure()。
3.ViewGroup里面只有measureChild(),measureChildWithMargins(),里面都会调用child.measure()方法。
所以准确的来说,其实ViewGroup的子类如果有重写onMeasure()方法,其实是重写了View的onMeasure()方法。
4.一般ViewGroup都会重写onMeasure(),然后里面一般计算child个数并循环调用child.measure()。
5.ps:发现FrameLayout里面有调用ViewGroup.measureChildWithMargins()和child.measure(),RelativeLayout里面只有child.measure()。LinearLayout里面有调用ViewGroup.meaChildWithMargins()和child.measure()。
measure流程
ViewRootImpl.doTraversal()->
ViewRootImpl.performTraversals()->
//开始测量
ViewRootImpl.performMeasure()->
    PhoneWindow$DecorView执行View.measure()->
    PhoneWindow$DecorView.onMeasure()->
    PhoneWindow$DecorView执行ViewGroup.measureChildWithMargins()child.measure()->

        LinearLayout执行View.measure()->
        LinearLayout.onMeasure()->
        LinearLayout执行ViewGroup.measureChildWithMargins()child.measure()->

            FrameLayout执行View.measure()->
            FrameLayout.onMeasure()->
            FrameLayout执行ViewGroup.measureChildWithMargins()child.measure()->

                RelativeLayout执行View.measure()->
                RelativeLayout.onMeasure()->
                RelativeLayout执行child.measure()->

                    TextView执行View.measure()->
                    TextView.onMeasure()

layout过程

view在layout过程中涉及的方法:
public void layout(int l, int t, int r, int b) {
...//省略代码
onLayout();
}
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {}
viewGroup在layout过程中涉及的方法:
public final void layout(int l, int t, int r, int b) {
        if (!mSuppressLayout && (mTransition == null || !mTransition.isChangingLayout())) {
            if (mTransition != null) {
                mTransition.layoutChange(this);
            }
            super.layout(l, t, r, b);
        } else {
            // record the fact that we noop'd it; request layout when transition finishes
            mLayoutCalledWhileSuppressed = true;
        }
    }
protected abstract void onLayout(boolean changed,
            int l, int t, int r, int b);
layout过程分析:
1.ViewGrouplayout()是final的,所以ViewGroup子类不可重写该方法。
2.ViewGrouplayout()实际上有调用super.layout(),即调用View的layout()。
3.ViewGrouponLayout()是抽象的,所以ViewGroup的子类必须重写该方法。
4.ViewGroup的子类像LinearLayout,FrameLayout,RelativeLayout等都重写了onLayout()方法,并且它们
的onLayout()方法里面都会调用了child.layout()方法。
5.Viewlayout()里面调用了onLayout(),onLayout()为空方法,所以View的子类是可以重写onLayout()方法的,一般情况下是不会重写onLayout()方法的。ps: TextView有重写,ImageView没有重写。
layout流程
ViewRootImpl.doTraversal()->
ViewRootImpl.performTraversals()->
//开始布局
ViewRootImpl.performLayout()->
    PhoneWindow$DecorView执行ViewGroup.layout()->
    PhoneWindow$DecorView.onLayout()->
    PhoneWindow$DecorView执行child.layout()->

        LinearLayout执行ViewGroup.layout()->
        LinearLayout.onLayout()->
        LinearLayout执行child.layout()->

            FrameLayout执行ViewGroup.layout()->
            FrameLayout.onLayout()->
            FrameLayout执行child.layout()->

                RelativeLayout执行ViewGroup.layout()->
                RelativeLayout.onLayout()->
                RelativeLayout执行child.layout()->

                    TextView执行View.layout()->
                    TextView.onLayout()

draw过程

view在draw过程中涉及的方法:
public void draw(Canvas canvas) {
...//省略代码
onDraw(canvas);
dispatchDraw(canvas);
}
protected void onDraw(Canvas canvas) {}
protected void dispatchDraw(Canvas canvas) {}
viewGroup在draw过程中涉及的方法:
protected void dispatchDraw(Canvas canvas) {...drawChild()}
protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
        return child.draw(canvas, this, drawingTime);
    }
draw过程分析:
1.drawChild方法是在ViewGroup的dispatchDraw()方法里面执行的。
2.发现LinearLayout和ViewPager重写了onDraw(),因为LinearLayout分横向和纵向布局。
一般情况下ViewGroup子类不会轻易重写draw(),onDraw(),dispatchDraw();即一般调用View.draw()
View.onDraw()空方法,ViewGroup.drawChild()。
3.一般情况下,View的子类都应该重写onDraw()方法。
draw流程
ViewRootImpl.doTraversal()->
ViewRootImpl.performTraversals()->
//开始绘制
ViewRootImpl.performDraw()->
    PhoneWindow$DecorView执行View.draw()->
    PhoneWindow$DecorView.onDraw()->
    PhoneWindow$DecorView执行ViewGroup.dispatchDraw()->
    PhoneWindow$DecorView执行ViewGroup.drawChild()->

        LinearLayout执行View.draw()->
        LinearLayout执行ViewGroup.dispatchDraw()->
        LinearLayout执行ViewGroup.drawChild()->

            FrameLayout执行View.draw()->
            FrameLayout执行ViewGroup.dispatchDraw()->
            FrameLayout执行ViewGroup.drawChild()->

                RelativeLayout执行View.draw()->
                RelativeLayout执行ViewGroup.dispatchDraw()->
                RelativeLayout执行ViewGroup.drawChild()->

                    TextView执行View.draw()->
                    TextView.onDraw()

参考资料

Android中View的量算、布局及绘图机制
Android应用层View绘制流程与源码分析
https://github.com/android/platform_frameworks_base/blob/master/core/java/android/view/View.java
https://github.com/android/platform_frameworks_base/blob/master/core/java/android/view/ViewGroup.java

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值