[Android] ConstaintLayout性能分析

Android ConstaintLayout性能分析

最近项目上大规模使用了ConstrainLayout,于是对性能进行一定的分析, 以及介绍一些使用心得。

性能分析

与RelativeLayout对比,基于HierarchyViewer

之前网上也有部分关于ConstrainLayout性能分析的文章,大部分是基于HierarchyViewer的,下面是分析的结果。

使用ConstrainLayout和RelativeLayout分别描述同样的布局,ConstrainLayout的measure时间明显比RelativeLayout的时间长。
基于ConstrainLayout 1.1.2。

随后Google搜下这类问题,发现同样有人遇到:

https://stackoverflow.com/questions/48704493/constraintlayout-onmeasure-very-slow

https://www.reddit.com/r/androiddev/comments/7ylbz3/is_constraintlayout_that_slow/

stackoverflow上ConstrainLayout团队给出了回答,大概是这样:

That’s definitely not expected – I’ll have to investigate more to see what’s causing it. Note that 1.1 beta is right now going to be slower than 1.0, all the optimizer passes aren’t enabled. At first glance there’s a lot of textview with 0dp width, which is pretty costly – like with linear layout, 0dp is going to result in a double measure.

就是说ConstrainLayout 1.1比1.0版本性能要差点。如果在ConstrainLayout中将View宽高指定成’MATCH_PARENT’,或者0dp。那么就会产生Measure两次的开销。

注意,此时有个关键点。ConstraintLayout子View的宽高尽量为具体数值或者WRAP_CONTENT,否则会重复进行测量两次

基于Android Runntime Test

下文同样提供了一种测试方案,我们尝试下。
同样基于ConstrainLayot 1.1.2。
https://medium.com/@krpiotrek/constraintlayout-performance-c1455c7984d7
https://github.com/krpiotrek/ConstraintLayoutPerformanceTest/blob/master/app/src/androidTest/java/com/krpiotrek/constraintlayoutstuff/PerformanceTest.java

public class PerformanceTest extends InstrumentationTestCase {

    @SmallTest
    public void test() {
        final long constraintLayoutTime = getLayoutTime(R.layout.item_new);
        final long linearLayoutTime = getLayoutTime(R.layout.item_old_linear);
        final long relativeLayoutTime = getLayoutTime(R.layout.item_old_relative);

        Log.i("time", "constraint : " + constraintLayoutTime);
        Log.i("time", "linear : " + linearLayoutTime);
        Log.i("time", "relative : " + relativeLayoutTime);
    }

    private long getLayoutTime(int layoutRes) {
        final Context targetContext = getInstrumentation().getTargetContext();
        final LayoutInflater layoutInflater = LayoutInflater.from(targetContext);

        final long startTime = System.currentTimeMillis();
        for (int i = 0; i < 1000; i++) {
            final View view = layoutInflater.inflate(layoutRes, null);
            view.setLayoutParams(new ViewGroup.LayoutParams(0, 0));

            view.measure(View.MeasureSpec.makeMeasureSpec(1000, View.MeasureSpec.EXACTLY), View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
            final int measuredHeight = view.getMeasuredHeight();
            final int measuredWidth = view.getMeasuredWidth();

            view.layout(0, 0, measuredWidth, measuredHeight);
        }
        return System.currentTimeMillis() - startTime;
    }
}

测试结果如下:

09-23 13:01:36.670 4191-4205/com.newtech.common.kotlintest I/time: constraint : 3997
    linear : 1712
    relative : 1424

可以看出ConstraintLayout的测量时间还是最长的。

基于Systrace的measure,layout性能分析

https://android-developers.googleblog.com/2017/08/understanding-performance-benefits-of.html

下面是我的测试数据
这次我们选用两个版本进行测量,看不同版本之间是否有明显的性能差异。

可以看出ConstrainLayout在1.1.X的版本性能确实比较糟糕,比RelativeLayout要差很多,上面几篇文章也印证了这个结论。

使用建议

  • 最好的选择还是FrameLayout和LinearLayout。

  • 如果单层LL,FL无法描述布局,使用单层RelativeLayout不需要嵌套的情况下,直接使用RelativeLayout即可。如果布局比较复杂,可以选用ConstrainLayout,ConstrainLayout在处理BaseLine之类的问题,比上面的布局都要方便。

  • 使用ConstrainLayout需要注意子View的MATCH_PARENT问题,在ConstrainLayout中,子View的MATCH_PARENT等同于0dp,都会造成两次测量。

总结

目前版本和RealtiveLayout性能还是有不小差距,如果你比较在乎性能,还是谨慎使用吧。
期待ConstrainLayout 2.0有更好的表现。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值