Android 佈局優化

驚天霸戈發表於2019-03-27

佈局是一個App非常關鍵的一部分,佈局效能的好壞可直接影響到使用者的體驗。試想下如果一個RecyclerView滑動時異常卡頓,那使用者估計也沒有心情去住下滑了,可能就直接強制殺掉App了去,然後回過頭去應用商店給個差評“卡的不要不要的”。雖然現在手機記憶體、CPU等各項效能都上來了看起來很強,實際上還是卡的不行,所以我們還是要多學習下效能優化方面的知識。

本文將分三個部分來介紹Android佈局優化的相關知識:

  • 優化佈局層級
  • 佈局重用
  • 按需載入佈局

優化佈局層級

優化佈局的層級是非常重要,大家都知道Android的佈局元素主可分為View和ViewGroup,其他LinearLayout、FrameLayout都是ViewGroup的子類。每個View在顯示之前都會有測量(measure)佈局(layout)繪製(draw)這三步,佈局層次越深相應的帶來的層級遍歷的消耗就越多。要優化佈局的層級可以使用Layout Inspector來分析某個View的測量、佈局、繪製所消耗的時間,幫助開發時定位佈局效能較差的點。

使用Layout Inspector非常方便,只需要簡單的幾步就能使用:

  1. 在連線的裝置或模擬器上執行您的應用
  2. 點選 Tools > Android > Layout Inspector。
  3. 在出現的 Choose Process 對話方塊中,選擇您想要檢查的應用程式,然後點選 OK。
  4. 選擇需要分析的Activity頁面
  5. 選擇Layout Inspector分析完成就可以檢視各項資料了。

如下圖所示Layout Inspector的主介面可分為三個部分:

  • View Tree:檢視在佈局中的層次結構。
  • Screenshot:帶每個檢視可視邊界的裝置螢幕截圖。
  • Properties Table:選定檢視的佈局屬性。

Android 佈局優化

使用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_widthlayout_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指定的佈局檔案替換掉。

相關文章