修正穩定性問題

遇到導致效能的不穩定類別時 建議您保持穩定本文件將概述幾個技巧 使用起來更為方便

啟用嚴格略過功能

請先嘗試啟用嚴格略過模式。加強略過模式 可讓系統略過含有不穩定參數的可組合項 方法,修正穩定性造成的效能問題。

詳情請參閱強式略過一文。

將類別設為不可變動

您也可以嘗試將不穩定的類別完全設為不可變動。

  • 不可變動:表示任何屬性的值都不可變更的類型 而所有方法都是由該類型的執行個體建構而成 也就是「公開透明」
    • 確認所有類別的屬性都是 val,而不是 var。 以及不可變動類型
    • String, IntFloat 等基本類型一律無法變更。
    • 如果不可行,您就必須將 Compose 狀態用於 任何可變動屬性
  • 穩定版:表示可變動的類型。Compose 執行階段不會 知悉任何類型的公開屬性或方法 行為就會與之前的叫用產生不同結果。
,瞭解如何調查及移除這項存取權。

不可變更的集合

Compose 認為類別不穩定的原因為集合。如先前所述 可以在「診斷穩定性問題」頁面中找到 Compose 編譯器 無法完全確保 List, MapSet 等集合 無法改變,因此標示為不穩定。

如要解決這個問題,您可以使用不可變動的集合。Compose 編譯器 包括支援 Kotlinx 不可變集合。這些 集合絕對無法變更,且 Compose 編譯器會將其視為 。此程式庫目前仍在 Alpha 測試階段,因此預期 API 可能會有異動。

請在診斷穩定性 問題指南:

unstable class Snack {
  
  unstable val tags: Set<String>
  
}

您可以使用不可變動的集合,將 tags 設為穩定版。在課程中變更 從 tagsImmutableSet<String> 的類型:

data class Snack{
    
    val tags: ImmutableSet<String> = persistentSetOf()
    
}

這麼做後,類別的所有參數都無法變更,而 Compose 編譯器會將類別標示為穩定版

並加上 StableImmutable 註解

可能的做法是將不穩定的類別加上註解 搭配 @Stable@Immutable 使用。

為類別加上註解將覆寫編譯器原本會如何處理 推測您的課程。這與 !! Kotlin 中的運算子。建議您 請謹慎使用這些註解覆寫編譯器行為 您可能會引發非預期的錯誤,例如可組合函式無法在發生下列情況時重組 符合期待

若能在沒有註解的情況下讓類別保持穩定,則您應 致力於達成這項目標

以下程式碼片段提供最精簡的資料類別範例,註解: 不可變動:

@Immutable
data class Snack(

)

無論您使用 @Immutable 還是 @Stable 註解,Compose 編譯器 將 Snack 類別標示為穩定版。

集合中的註解類別

假設可組合函式包含 List<Snack> 類型的參數:

restartable scheme("[androidx.compose.ui.UiComposable]") fun HighlightedSnacks(
  
  unstable snacks: List<Snack>
  
)

即使您使用 @ImmutableSnack 加上註解,Compose 編譯器仍會標記 HighlightedSnacks 中的 snacks 參數並不穩定。

參數在收集類型方面會面臨與類別相同的問題 Compose 編譯器一律會將 List 類型的參數標示為不穩定, 尤其是一系列穩定類型

您無法將個別參數標示為穩定版,也無法為 設為一律可略過的可組合函式路徑向前有很多,

有幾種方式可以解決集合不穩定的問題。 以下各小節將概略說明這些不同做法。

設定檔

如果您願意遵守程式碼集的穩定性合約, 您可以選擇將 Kotlin 集合視為穩定版,方法是新增 訊息張貼時間:kotlin.collections.*,分享對象: 穩定性設定檔

不可變更的集合

如要確保編譯時間的不變性,您可以 使用 kotlinx 的不可變集合,而不是 List

@Composable
private fun HighlightedSnacks(
    
    snacks: ImmutableList<Snack>,
    
)

Wrapper

如果您無法使用不可變更的集合,可以自行建立集合。方法如下 將 List 納入已加註的穩定類別中。一般包裝函式可能是 根據你的需求提供最合適的選項

@Immutable
data class SnackCollection(
   val snacks: List<Snack>
)

並在可組合函式中,將其做為參數類型。

@Composable
private fun HighlightedSnacks(
    index: Int,
    snacks: SnackCollection,
    onSnackClick: (Long) -> Unit,
    modifier: Modifier = Modifier
)

解決方案

採用上述任一方法後,Compose 編譯器現在會標記 HighlightedSnacks 可組合函式同時包含 skippablerestartable

restartable skippable scheme("[androidx.compose.ui.UiComposable]") fun HighlightedSnacks(
  stable index: Int
  stable snacks: ImmutableList<Snack>
  stable onSnackClick: Function1<Long, Unit>
  stable modifier: Modifier? = @static Companion
)

在重組期間,如果 Compose 沒有 HighlightedSnacks 輸入內容已變更

穩定性設定檔

從 Compose Compiler 1.5.5 開始,將類別的設定檔 開發人員可以在編譯期間提供穩定性同時,您可以考慮 您無法控管的類別,例如標準程式庫類別 就像 LocalDateTime 一樣穩定

設定檔是純文字檔案,每列包含一個類別,留言, 單行和雙萬用字元都支援。 設定範例如下:

// Consider LocalDateTime stable
java.time.LocalDateTime
// Consider kotlin collections stable
kotlin.collections.*
// Consider my datalayer and all submodules stable
com.datalayer.**
// Consider my generic type stable based off it's first type parameter only
com.example.GenericClass<*,_>

如要啟用這項功能,請將設定檔的路徑傳遞至 Compose 編譯器選項。

Groovy

kotlinOptions {
    freeCompilerArgs += [
            "-P",
            "plugin:androidx.compose.compiler.plugins.kotlin:stabilityConfigurationPath=" +
                    project.absolutePath + "/compose_compiler_config.conf"
    ]
}

Kotlin

kotlinOptions {
  freeCompilerArgs += listOf(
      "-P",
      "plugin:androidx.compose.compiler.plugins.kotlin:stabilityConfigurationPath=" +
      "${project.absolutePath}/compose_compiler_config.conf"
  )
}

由於 Compose 編譯器分別在專案中的每個模組上執行,因此您可以 並視需要為不同的模組提供不同設定。或者,持有 並將該路徑傳送至 後續課程我們將逐一介紹 預先訓練的 API、AutoML 和自訂訓練

多個模組

另一個常見問題涉及多模組架構。Compose 編譯器 只有在所有 該參照會明確標示為穩定,或者在記錄為 建構而成

如果資料層位於 UI 層的獨立模組中,也就是 這可能是你遇到的問題

解決方案

如要解決這個問題,您可以採取下列其中一種做法:

  1. 新增類別至編譯器設定檔
  2. 在資料層模組中啟用 Compose 編譯器,或標記類別 隨附 @Stable@Immutable
    • 包括在資料層中加入 Compose 依附元件。不過 這只是 Compose 執行階段的依附元件,不是 Compose-UI
  3. 在 UI 模組中,將資料層類別納入 UI 專屬包裝函式中 類別

使用外部程式庫時,如果未使用 Compose 編譯器。

並非所有可組合項都應該可略過

修正穩定性問題時,請不要為了 可略過的可組合函式。嘗試這樣做可能會使最佳化作業尚未成熟 而不是問題修正

在許多情況下,可略過廣告並沒有什麼實質好處 可能會導致程式碼難以維護例如:

  • 不常或完全不重組的可組合函式。
  • 本身只會呼叫可略過的可組合函式。
  • 具有大量參數且價格等值的可組合項 。在此情況下,檢查任何參數 所花費的比率可能會遠超過 成本低廉的重組成本

如果是可略過的可組合項,就會增加一點負擔,而這可能不甚理想 基礎架構在某些情況下,您甚至可以將可組合函式加註為無法重新啟動 您判斷可重新啟動的負擔高於費用。