佈局是一個App非常關鍵的一部分,佈局效能的好壞可直接影響到使用者的體驗。試想下如果一個RecyclerView
滑動時異常卡頓,那使用者估計也沒有心情去住下滑了,可能就直接強制殺掉App了去,然後回過頭去應用商店給個差評“卡的不要不要的”。雖然現在手機記憶體、CPU等各項效能都上來了看起來很強,實際上還是卡的不行,所以我們還是要多學習下效能優化
方面的知識。
本文將分三個部分來介紹Android佈局
優化的相關知識:
- 優化佈局層級
- 佈局重用
- 按需載入佈局
優化佈局層級
優化佈局的層級是非常重要,大家都知道Android的佈局元素主可分為View和ViewGroup,其他LinearLayout、FrameLayout都是ViewGroup的子類。每個View在顯示之前都會有測量(measure)
、佈局(layout)
、繪製(draw)
這三步,佈局層次越深相應的帶來的層級遍歷的消耗就越多。要優化佈局的層級可以使用Layout Inspector
來分析某個View的測量、佈局、繪製所消耗的時間,幫助開發時定位佈局效能較差的點。
使用Layout Inspector
非常方便,只需要簡單的幾步就能使用:
- 在連線的裝置或模擬器上執行您的應用
- 點選 Tools > Android > Layout Inspector。
- 在出現的 Choose Process 對話方塊中,選擇您想要檢查的應用程式,然後點選 OK。
- 選擇需要分析的Activity頁面
- 選擇
Layout Inspector
分析完成就可以檢視各項資料了。
如下圖所示Layout Inspector
的主介面可分為三個部分:
- View Tree:檢視在佈局中的層次結構。
- Screenshot:帶每個檢視可視邊界的裝置螢幕截圖。
- Properties Table:選定檢視的佈局屬性。
使用Layout Inspector
分析佈局層次後就可以對佈局的層次做一些改動,以下是一些小技巧大家可參考優化佈局層級:
- 使用 ConstraintLayout
- 使用
merge
標籤 - 使用
compound drawable
佈局重用
佈局重用是開發過程中非常重要的一部分,這樣能減少多餘的佈局檔案和維護成品。在Android中佈局重用可以使用<include>
標籤,它可以高效重用完整的佈局,比如有多個Activity中都有一個底部的Button
除了文字不同以外其餘的樣式都基本相同,這樣只需要建立一個底部按鈕佈局檔案,然後在Activity的佈局中通過<include>
標籤引用按鈕的佈局就可以實現一個統一按鈕。
根據上面提到的例子新建一個layout_bottom_button.xml
的佈局檔案:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:tools="http://schemas.android.com/tools"
android:background="@android:color/white"```
<include
layout="@layout/layout_bottom_button"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
>
<Button
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_margin="5dp"
android:background="#36b7f7"
android:textColor="@android:color/white"
tools:text="下一步"
/>
</FrameLayout>
複製程式碼
然後再建立一個新的佈局檔案,使用<include>
標籤包含上面的佈局:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="match_parent">
<include layout="@layout/layout_bottom_button"/>
</FrameLayout>
複製程式碼
只需要簡單幾步就能實現佈局的重用,同時還可以重新覆蓋佈局引數:
<include
layout="@layout/layout_bottom_button"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
複製程式碼
需要注意的是,覆蓋佈局引數時必需要覆蓋layout_width
和layout_height
這兩個引數。
按需載入佈局
有些時候佈局會需要一些其它的View
,但它們不是一開始就顯示到介面上,比如進度條、提示訊息等元素,它們只會在特點的場景下才會出現,類似這樣的場景可以使用<ViewStub>
標籤來處理在需要的時候載入View
。
ViewStub
是一個輕量級的View
,它不會顯示到介面上,它只會在你需要的時候載入將佈局載入到佈局層次中。ViewStub
的使用非常簡單隻需要一個android:layout
屬性來指定需要替換的佈局檔案就可以了:
<ViewStub
android:id="@+id/stub_import"
android:inflatedId="@+id/panel_import"
android:layout="@layout/progress_overlay"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom" />
複製程式碼
當你需要載入android:layout
指定的佈局檔案時,只需要呼叫setVisibility(View.VISIBLE)
或inflate()
方法就能將ViewStub
替換成android:layout
指定的佈局:
findViewById(R.id.stub_import).setVisibility(View.VISIBLE);
// or
View importPanel = ((ViewStub) findViewById(R.id.stub_import)).inflate();
複製程式碼
用setVisibility(View.VISIBLE)
或inflate()
方法後,ViewStub
將不再是佈局層次中的一部分,它會被android:layout
指定的佈局檔案替換掉。