從五年前剛接觸Android開發,到初入職場。不管想寫什麼小demo,或者做什麼課程設計,拿到需求,我就開始自己的線性佈局之旅了。不管多麼複雜的佈局,我幾乎都能通過各種嵌套來實現。但是,逐漸的,我也聽到身邊的同事說線性佈局嵌套會導致過度繪製,影響性能等等的說法。那時,我還一臉懵逼。確實,那時候,我也只是想着完成功能。
那麼,爲什麼我想寫一篇文章來對比一下這三種佈局的性能呢?因爲,以前我用線性佈局,有同事說相對佈局好一些,然後我會適量的使用相對佈局。後來,隨着約束佈局的出現和使用人羣日漸增多,我在否定約束佈局很久後,終於也沒逃過“真香定理”。確實,約束佈局她太香了。嘗試過一次約束佈局後,我開始大量的使用,以至於我最喜歡的線性佈局,我都很少去觸碰它了。但是,我確實沒有自己去驗證一下,這三種佈局是否在性能上的差別。好,接下來,我就以我的方式去對比一下這三種佈局的性能。
一.從需求入手
首先,我們給自己一個需求。就做一個老生常談的登錄界面吧!很簡單的登錄界面:
二.性能比較
首先,說明一下,這裏的性能比較是在不嵌套佈局的情況下去對比。我們分別用線性佈局,相對佈局和約束佈局去實現上面的登錄界面。比較方式:我們在這裏也沒有去詳細的比較繪製的三個流程分別耗時多少,我們就打印一下setContentView的耗時情況。(注:(1)不統計除此啓動耗時(2)均爲殺死進程後重新啓動(3)測試手機爲小米Max 2)
long startTime = System.currentTimeMillis();
setContentView(R.layout.activity_main_linear);
long endTime = System.currentTimeMillis();
long totalTime = endTime-startTime;
Log.d("TTTT","totalTime:"+totalTime);
1.線性佈局
(1)代碼:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<EditText
android:id="@+id/edt_1"
android:layout_width="200dp"
android:layout_height="40dp"
android:layout_gravity="center_horizontal"
android:layout_marginTop="200dp" />
<EditText
android:id="@+id/edt_2"
android:layout_width="200dp"
android:layout_height="40dp"
android:layout_gravity="center_horizontal"
android:layout_marginTop="10dp" />
<Button
android:id="@+id/button"
android:layout_width="200dp"
android:layout_height="40dp"
android:text="login in"
android:layout_gravity="center_horizontal"
android:layout_marginTop="10dp" />
</LinearLayout>
(2)耗時情況
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 平均 |
130 | 129 | 131 | 130 | 129 | 132 | 131 | 131 | 129 | 129 | 130 |
2.相對佈局
(1)代碼
<?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="match_parent"
tools:context=".MainActivity">
<EditText
android:id="@+id/edt_1"
android:layout_width="200dp"
android:layout_height="40dp"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="200dp" />
<EditText
android:id="@+id/edt_2"
android:layout_width="200dp"
android:layout_height="40dp"
android:layout_below="@+id/edt_1"
android:layout_centerHorizontal="true"
android:layout_marginTop="10dp" />
<Button
android:id="@+id/button"
android:layout_width="200dp"
android:layout_height="40dp"
android:layout_below="@+id/edt_2"
android:text="login in"
android:layout_centerHorizontal="true"
android:layout_marginTop="10dp" />
</RelativeLayout>
(2)耗時情況
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 平均 |
132 | 130 | 130 | 131 | 128 | 129 | 130 | 127 | 129 | 130 | 130 |
3.約束佈局
(1)代碼
<?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="match_parent"
tools:context=".MainActivity">
<EditText
android:id="@+id/edt_1"
android:layout_width="200dp"
android:layout_height="40dp"
android:layout_marginTop="200dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<EditText
android:id="@+id/edt_2"
android:layout_width="200dp"
android:layout_height="40dp"
android:layout_marginTop="10dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/edt_1" />
<Button
android:id="@+id/button"
android:layout_width="200dp"
android:layout_height="40dp"
android:layout_marginTop="10dp"
android:text="login in"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/edt_2" />
</androidx.constraintlayout.widget.ConstraintLayout>
(2)耗時情況
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 平均 |
160 | 163 | 163 | 162 | 161 | 159 | 168 | 168 | 156 | 158 | 162 |
4.比較結果
經過上面的數據,我們可以看出,在簡單佈局下,相對佈局和線性佈局的耗時情況差不多。但是,約束佈局的耗時反而會多了30ms。大家都知道,在不考慮佈局嵌套的情況下,相對佈局由於會在measure中計算兩次,會導致耗時比線性佈局稍微多一些。而約束佈局是相對佈局的進化版,在處理簡單佈局的時候,耗時確實有所增加。
三.個人觀點
根據自己的實際工作,以及瞭解到的一些同事對佈局的使用情況,說一下個人的幾個觀點:
(1)在佈局簡單的情況下,優先使用LinearLayout,其次考慮RelativeLayout和ConstraintLayout。原因:簡單佈局下,LinearLayout確實簡單,且耗時不多,代碼量也相對少一些。
(2)在佈局比較複雜的情況下,優先使用RelativeLayout和ConstraintLayout,不建議使用LinearLayout各種嵌套。原因:佈局過多層次的嵌套,會增加繪製時間。
(3)不必刻意追求使用ConstraintLayout,如果你習慣了使用RelativeLayout。原因:ConstraintLayout和RelativeLayout在處理複雜佈局時,我沒做過更多的耗時比較。但是,有很多人確實習慣使用RelativeLayout,那麼,也不必強行使用約束佈局,因爲有些人會覺得約束佈局會寫很多的代碼。。。