持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第8天,点击查看活动详情
ConstraintLayout 性能对比与分析
关于 ConstraintLayout 的介绍就不用多说了吧,到今天来说已经是基本控件了,如果真有不会用的看官网介绍。
现在感觉大家都已经有点神话 ConstraintLayout 了,现在创建 Activity 的 xml 。默认的根布局就是 ConstraintLayout 了,咋滴,真要我们把全部页面都用一个 ConstraintLayout 包裹吗?
百度搜索一下 ConstraintLayout 。全是优化布局!!!
我心里打个问号?真有这么强?ConstraintLayout 就无敌了?
这里我用 LinearLayout RelativeLayout ConstraintLayout 做一个对比,实现同样的效果,三种布局分别来实现,看看耗时多少!
耗时方法统计为 设置布局之前与展示布局之后。
override fun onCreate(savedInstanceState: Bundle?) {
start = System.currentTimeMillis()
super.onCreate(savedInstanceState)
}
override fun onResume() {
super.onResume()
end = System.currentTimeMillis()
YYLogUtils.w("耗时:" + (end - start))
}
复制代码
一、简单布局测试
实现一个简单的2行文本
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="@dimen/d_15dp"
android:paddingBottom="@dimen/d_15dp"
tools:background="@color/white">
<TextView
android:id="@+id/tv_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="君不见," />
<TextView
android:id="@+id/tv_2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:text="黄河之水天上来" />
<TextView
android:id="@+id/tv_3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:text="奔流到海不复回" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/tv_1"
android:layout_marginTop="@dimen/d_10dp"
android:text="君不见" />
<TextView
android:layout_below="@id/tv_1"
android:layout_marginTop="@dimen/d_10dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:text="高堂明镜悲白发" />
<TextView
android:layout_below="@id/tv_1"
android:layout_marginTop="@dimen/d_10dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:text="朝如青丝暮成雪" />
</RelativeLayout>
复制代码
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="@dimen/d_15dp"
android:paddingBottom="@dimen/d_15dp"
tools:background="@color/white">
<TextView
android:id="@+id/tv_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="君不见,"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tv_2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="黄河之水天上来"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tv_3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:text="奔流到海不复回"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tv_4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/d_10dp"
android:layout_weight="1"
android:text="君不见,"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_1" />
<TextView
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="@id/tv_4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:text="高堂明镜悲白发" />
<TextView
app:layout_constraintTop_toTopOf="@id/tv_4"
app:layout_constraintRight_toRightOf="parent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="right"
android:text="朝如青丝暮成雪" />
</androidx.constraintlayout.widget.ConstraintLayout>
复制代码
结果:
LinearLayout | RelativeLayout | ConstraintLayout |
---|---|---|
53 | 53 | 61 |
57 | 54 | 54 |
52 | 53 | 54 |
51 | 52 | 59 |
52 | 62 | 53 |
53 | 59 | 53 |
结果是简单布局实现 LinearLayout 更优秀。RelativeLayout 和 ConstraintLayout 的 区别不大。
二、稍微复杂布局测试
实现的效果如下:
这里我们就不贴重复的代码了,实现的方式与上面类似。同样的效果只是多添加几层,看看实现的结果。
LinearLayout | RelativeLayout | ConstraintLayout |
---|---|---|
83 | 83 | 85 |
85 | 81 | 87 |
86 | 84 | 93 |
83 | 83 | 85 |
99 | 81 | 84 |
86 | 82 | 86 |
稍微复杂的布局中,,确实 RelativeLayout 和 ConstraintLayout 这种布局实现减少层级之后确实展示的更快了。LinearLayout 已经没有优势了!但是这里 RelativeLayout 的要比 ConstraintLayout 强一点!
话不多说,我们看看比较复杂的布局测试。
三、比较复杂布局测试
实现效果如下:
一共14行布局,我们就不贴重复的代码了,实现的方式与上面类似。都是很基本的实现方式了,我们直接看看结果。
LinearLayout | RelativeLayout | ConstraintLayout |
---|---|---|
140 | 162 | 156 |
140 | 144 | 163 |
150 | 155 | 165 |
142 | 144 | 159 |
140 | 147 | 152 |
153 | 150 | 161 |
可以看到在比较复杂的布局中,LinearLayout 又赶超上来了,这里 RelativeLayout 与 ConstraintLayout 的性能差不多了。
可以看到在比较复杂的布局中还是不太推荐 全部一个 ConstraintLayout 包裹实现。
四、RV列表中的使用
这是静态布局的展示,那么在列表中的使用性能又如何呢?
这里直接上图吧!
ConstraintLayout 的Item布局实现,明显卡顿,都已经超出屏幕外了。后续往回拉动展示缓存布局的时候也会超出16.6ms。 会出现轻微的卡顿。
LinearLayout 的情况与 RelativeLayout 的布局类似,虽然也卡,但是没有那么的明显。后续往回拉动展示缓存布局的时候也明显帧数更低。不会出现卡顿。
为什么出现这种情况。我们看看相同的布局 他们 onMeasure onLayout onDraw的耗时。(注:这里的耗时是纳秒)
Cons01 onMeasure - 27323438
Cons01 onMeasure - 22129271
Cons01 onLayout - 3678230
Cons01 onDraw - 5311458
Rel01 onMeasure - 8344687
Rel01 onMeasure - 1069531
Rel01 onLayout - 2910156
Rel01 onDraw - 4294010
Lin01 onMeasure - 3184948
Lin01 onMeasure - 3351094
Lin01 onLayout - 5469532
Lin01 onDraw - 5566250
每一个布局的展示都是两次onMeasure 一次onLayout 一次onDraw。这都是正常的,因为ViewGroup要先测量子布局再测量自己。
重点是看 ConstraintLayout 的测量耗时,这也太那啥了,ConstraintLayout 测量的耗时为 LinearLayout 的8倍。
五、总结
当前使用的 ConstraintLayout 测试版本为2.0.3 非最新版本,测试机型为7.0老款机型,本人非专业测试,测试工具也不专业,当前测试结果仅供参考。
尽管如此,我们还是可以得到大致的结论。
ConstraintLayout 并没有比 RelativeLayout性能好到哪里去。在简单的布局和复杂的布局中 LinearLayout 还是YYDS。 在稍微复杂的布局中,我们确实可以通过减少层级优化布局加载数据,此时使用 ConstraintLayout 确实不错。
在复杂的布局中我们可以使用 LinearLayout 作为根视图,内部的每一个稍微复杂的布局View,我们可以用 ConstraintLayout 布局,做到 LinearLayout + ConstraintLayout 的布局方式,这才是最优解(吧?)
在列表中尽量避免使用 ConstraintLayout 做Item的整个根视图,测量会比较耗时。推荐使用 LinearLayout ,或者 LinearLayout + ConstraintLayout 的布局方式。
话虽如此,但是 ConstraintLayout 的一些新特效确实太香,比如百分比布局,宽高比例布局适配太方便,比如 ConstraintLayout 中的 MotionLayout 做动画也太方便了趴。
所以,布局的应用就这样了。有了自己的思考,就知道如何组合的使用 ViewGroup 布局,如果真的全部使用 ConstraintLayout 来布局,那不得卡到爆。
OK,说了这么多,如果大家有不同意见,欢迎到评论区留言哦。
到处完结。