1. 程式人生 > >[Android] ConstaintLayout效能分析

[Android] ConstaintLayout效能分析

Android ConstaintLayout效能分析

最近專案上大規模使用了ConstrainLayout,於是對效能進行一定的分析, 以及介紹一些使用心得。

效能分析

與RelativeLayout對比,基於HierarchyViewer

之前網上也有部分關於ConstrainLayout效能分析的文章,大部分是基於HierarchyViewer的,下面是分析的結果。

使用ConstrainLayout和RelativeLayout分別描述同樣的佈局,ConstrainLayout的measure時間明顯比RelativeLayout的時間長。
基於ConstrainLayout 1.1.2。

隨後Google搜下這類問題,發現同樣有人遇到:

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

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效能分析

下面是我的測試資料
這次我們選用兩個版本進行測量,看不同版本之間是否有明顯的效能差異。

可以看出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有更好的表現。