遇到導致效能的不穩定類別時 建議您保持穩定本文件將概述幾個技巧 使用起來更為方便
啟用嚴格略過功能
請先嘗試啟用嚴格略過模式。加強略過模式 可讓系統略過含有不穩定參數的可組合項 方法,修正穩定性造成的效能問題。
詳情請參閱強式略過一文。
將類別設為不可變動
您也可以嘗試將不穩定的類別完全設為不可變動。
- 不可變動:表示任何屬性的值都不可變更的類型
而所有方法都是由該類型的執行個體建構而成
也就是「公開透明」
- 確認所有類別的屬性都是
val
,而不是var
。 以及不可變動類型 String, Int
和Float
等基本類型一律無法變更。- 如果不可行,您就必須將 Compose 狀態用於 任何可變動屬性
- 確認所有類別的屬性都是
- 穩定版:表示可變動的類型。Compose 執行階段不會 知悉任何類型的公開屬性或方法 行為就會與之前的叫用產生不同結果。
不可變更的集合
Compose 認為類別不穩定的原因為集合。如先前所述
可以在「診斷穩定性問題」頁面中找到 Compose 編譯器
無法完全確保 List, Map
和 Set
等集合
無法改變,因此標示為不穩定。
如要解決這個問題,您可以使用不可變動的集合。Compose 編譯器 包括支援 Kotlinx 不可變集合。這些 集合絕對無法變更,且 Compose 編譯器會將其視為 。此程式庫目前仍在 Alpha 測試階段,因此預期 API 可能會有異動。
請在診斷穩定性 問題指南:
unstable class Snack {
…
unstable val tags: Set<String>
…
}
您可以使用不可變動的集合,將 tags
設為穩定版。在課程中變更
從 tags
到 ImmutableSet<String>
的類型:
data class Snack{
…
val tags: ImmutableSet<String> = persistentSetOf()
…
}
這麼做後,類別的所有參數都無法變更,而 Compose 編譯器會將類別標示為穩定版
並加上 Stable
或 Immutable
註解
可能的做法是將不穩定的類別加上註解
搭配 @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>
…
)
即使您使用 @Immutable
為 Snack
加上註解,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
可組合函式同時包含 skippable
和 restartable
。
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 層的獨立模組中,也就是 這可能是你遇到的問題
解決方案
如要解決這個問題,您可以採取下列其中一種做法:
- 新增類別至編譯器設定檔。
- 在資料層模組中啟用 Compose 編譯器,或標記類別
隨附
@Stable
或@Immutable
。- 包括在資料層中加入 Compose 依附元件。不過
這只是 Compose 執行階段的依附元件,不是
Compose-UI
。
- 包括在資料層中加入 Compose 依附元件。不過
這只是 Compose 執行階段的依附元件,不是
- 在 UI 模組中,將資料層類別納入 UI 專屬包裝函式中 類別
使用外部程式庫時,如果未使用 Compose 編譯器。
並非所有可組合項都應該可略過
修正穩定性問題時,請不要為了 可略過的可組合函式。嘗試這樣做可能會使最佳化作業尚未成熟 而不是問題修正
在許多情況下,可略過廣告並沒有什麼實質好處 可能會導致程式碼難以維護例如:
- 不常或完全不重組的可組合函式。
- 本身只會呼叫可略過的可組合函式。
- 具有大量參數且價格等值的可組合項 。在此情況下,檢查任何參數 所花費的比率可能會遠超過 成本低廉的重組成本
如果是可略過的可組合項,就會增加一點負擔,而這可能不甚理想 基礎架構在某些情況下,您甚至可以將可組合函式加註為無法重新啟動 您判斷可重新啟動的負擔高於費用。