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

内容

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

测试试图结构:

Android 不同布局类型measure、layout、draw耗时对比_第1张图片

测试方式

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

结果(单位:ms):

Android 不同布局类型measure、layout、draw耗时对比_第2张图片

代码:

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时间,加油少年!

你可能感兴趣的:(Android学习)