Compose 的穩定性

Compose 會將類型視為穩定版或不穩定。如果類型不可變動,或 Compose 可能知道該類型的值是否在重組之間發生變化,就會保持穩定。如果 Compose 不知道該類型的值是否在重組之間發生變化,就不穩定。

Compose 會根據可組合項參數的穩定性,判斷能否在重組期間略過可組合項:

  • 穩定版參數:如果可組合項含有未變更的穩定參數,Compose 會略過該參數。
  • 不穩定的參數:如果可組合項含有不穩定的參數,Compose 一律會在重組元件的父項時重組。

如果應用程式含有許多非必要的元件,而 Compose 一律會重組,則您可能會觀察到效能問題和其他問題。

本文件詳細說明如何提高應用程式的穩定性,以改善效能和整體使用者體驗。

不可變動的物件

下列程式碼片段說明穩定性和重組背後的一般原則。

Contact 類別是不可變動的資料類別。這是因為所有參數都是以 val 關鍵字定義的原始項目。建立 Contact 的執行個體後,就無法變更物件屬性的值。如果嘗試這麼做,請建立一個新的物件。

data class Contact(val name: String, val number: String)

ContactRow 可組合項具有 Contact 類型的參數。

@Composable
fun ContactRow(contact: Contact, modifier: Modifier = Modifier) {
   var selected by remember { mutableStateOf(false) }

   Row(modifier) {
      ContactDetails(contact)
      ToggleButton(selected, onToggled = { selected = !selected })
   }
}

請考量使用者按下切換按鈕且 selected 狀態變更時會發生什麼事:

  1. Compose 會評估是否應在 ContactRow 中重組程式碼。
  2. 您會看到 ContactDetails 的唯一引數是 Contact 類型。
  3. 由於 Contact 是不可變動的資料類別,因此 Compose 可確保 ContactDetails 的引數都維持不變。
  4. 因此,Compose 會略過 ContactDetails,且不會重組。
  5. 另一方面,ToggleButton 的引數已變更,而 Compose 會重新組合該元件。

可變動的物件

雖然上述範例使用不可變動的物件,但您可以建立可變動物件。請參考以下程式碼片段:

data class Contact(var name: String, var number: String)

由於 Contact 的每個參數現在都是 var,類別已不可變動。如果其屬性有所變更,Compose 就不會察覺。這是因為 Compose 只會追蹤 Compose 狀態物件的變更。

Compose 將這類類別視為不穩定。Compose 不會略過不穩定類別的重組作業。因此,如果以這種方式定義 Contact,上一個範例中的 ContactRow 會在每次 selected 變更時重組。

在 Compose 中實作

想想 Compose 如何確切決定要在重組期間略過哪些函式,但這可能很有幫助。

Compose 編譯器在您的程式碼上執行時,會使用數個標記之一來標記每個函式和類型。這些標記反映了 Compose 在重組期間處理函式或類型的方式。

函式

Compose 可以將函式標示為 skippablerestartable。請注意,這些函式可能會將函式標示為「一」、「兩者」或「兩者皆非」:

  • 可略過:如果編譯器將某個可組合項標示為可略過,只要其引數與先前的值都相同,Compose 即可在重組期間略過。
  • 可重新啟動:可重新啟動的可組合項可做為可以開始重組的「範圍」。換句話說,函式可以是進入點,其中 Compose 可以在狀態變更後開始重新執行程式碼,以便重組。

類型

Compose 將類型標示為不可變動或穩定版。每個類型都是其中之一:

  • 不可變動:如果類型的值永遠不會變更,且所有方法皆為透明,Compose 會將該類型標示為不可變動。
    • 請注意,所有原始類型都標示為不可變動。包括 StringIntFloat
  • 穩定版:表示建構後屬性可以變更的類型。如果這些屬性在執行階段期間有所變更,Compose 就會知道這類變更。

偵錯穩定性

如果應用程式正在重組參數未變更的可組合項,請先檢查其定義,找出可明顯變動的參數。如果您傳入包含 var 屬性的類型,或採用已知無法穩定類型的 val 屬性,Compose 一律會重組元件。

如要進一步瞭解如何在 Compose 中診斷穩定性的複雜問題,請參閱「對穩定性進行偵錯」指南。

修正穩定性問題

如要瞭解如何為 Compose 實作提升穩定性,請參閱「修正穩定性問題」指南。

摘要

整體來說,您應注意下列要點:

  • 參數:Compose 會決定可組合項中每個參數的穩定性,藉此判斷在重組期間應略過哪些可組合項。
  • 立即修正:如果您發現系統沒有略過可組合元件,且會造成效能問題,請先查看造成效能不穩定的明確原因,例如 var 參數。
  • 編譯器報表:您可以使用編譯器報表,判斷系統推論類別的相關穩定性。
  • 集合:Compose 一律會將集合類別視為不穩定,例如 List, SetMap。這是因為系統無法保證這些變數無法變更。您可以改用 Kotlinx 不可變動的集合,或是將類別加註 @Immutable@Stable
  • 其他模組:Compose 一律會將 Compose 編譯器執行的模組不穩定。如有需要,請將類別納入 UI 模型類別。

其他資訊