Android 不一样布局类型measure、layout、draw耗时对比

内容

RelativeLayout、LinearLayout、FrameLayout、ConstraintLayout这四种类型的measure、layout、draw耗时对比。java

测试试图结构:

结构

测试方式

使用一个结构很是深的试图结构,重复执行measure、layout、draw各1000次。计算耗时。web

结果(单位:ms):

测试结果

代码:

public class MainActivity extends Activity {

    private Handler mHandler = new Handler();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ViewGroup root = new FrameLayout(this) {
            @Override
            protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
                long l = System.nanoTime();
                super.onMeasure(widthMeasureSpec, heightMeasureSpec);
                timeMillis += (System.nanoTime() - l);
                if (++count == 1000) {
                    Log.e("cww", "finish measure: " + timeMillis);
                } else {
                    if (count < 1000) {
                        mHandler.postDelayed(new Runnable() {
                            @Override
                            public void run() {
                                view.requestLayout();
                                view.invalidate();
                            }
                        }, 0);
                    }
                }
            }

            @Override
            protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
                long l = System.nanoTime();
                super.onLayout(changed, left, top, right, bottom);
                timeMillis2 += (System.nanoTime() - l);
                if (count == 1000) {
                    Log.e("cww", "finish layout: " + timeMillis2);
                }
            }

            @Override
            protected void dispatchDraw(Canvas canvas) {
                long l = System.nanoTime();
                super.dispatchDraw(canvas);
                timeMillis3 += (System.nanoTime() - l);
                if (count == 1000) {
                    Log.e("cww", "finish draw: " + timeMillis3);
                }
            }

        };

        setContentView(root);

        for (int i = 0; i < 10; i++) {
            FrameLayout rootLocal = new FrameLayout(this);
            root.addView(rootLocal);
            root = rootLocal;
        }

        view = new View(this);
        root.addView(view);
    }

    View view;

    private int count = 0;
    private long timeMillis = 0;
    private long timeMillis2 = 0;
    private long timeMillis3 = 0;

总结

  1. 能够看出,各类布局除了measure差异比较大外,layout和draw耗时差异不大。
  2. RelativeLayout在measure这一步耗时贼JB严重。是由于相对布局须要给全部子View水平方向测量一次,再竖直方向测量一次,才能肯定每一个子View的大小。层级一旦太深,measure时间以指数上升。
  3. 若是能够,在不增长嵌套的状况下,尽可能使用FrameLayout。FrameLayout可以实现重心,经过Gravity来实现。别老爱用RelativeLayout的AlignParentxxx属性
  4. LinearLayout若是子View的LayoutParams里有使用weight属性的话,measure时间和RelativeLayout几乎接近,由于也须要给每一个子View测量两次。
  5. ConstraintLayout是Google新推出的一个布局,在性能上比RelativeLayout好,比LinearLayout差一些。
  6. 尽可能少写层级深的布局,能减小一个试图节点就少一些measure时间,加油少年!