強式略過模式

嚴格略過是 Compose 編譯器提供的模式。啟用後,會以兩種方式變更編譯器的行為:

  • 含有不穩定參數的可組合函式會變成可略過
  • 含有不穩定擷取內容的 lambda 會記錄

啟用嚴格略過模式

根據預設,Kotlin 2.0.20 會啟用強制略過功能。

如要在 2.0.20 以下版本中為 Gradle 模組啟用強制略過功能,請在 Gradle 設定的 composeCompiler 區塊中加入下列選項:

android { ... }

composeCompiler {
   enableStrongSkippingMode = true
}

可組合函式可略過性

強制略過模式會放寬 Compose 編譯器在略過和可組合函式時通常會套用的部分穩定性規則。根據預設,如果可組合函式的所有引數都具有穩定的值,Compose 編譯器會將該函式標示為可略過。嚴格略過模式會改變這項設定。

啟用強制略過功能後,所有可重新啟動的可組合函式都會變成可略過的函式。無論是否含有不穩定的參數,這項做法都適用。無法重新啟動的可組合函式仍無法略過。

略過時機

為了判斷是否要在重新組合期間略過可組合項,Compose 會將每個參數的值與先前的值進行比較。比較類型取決於參數的穩定性

  • 系統會使用例項相等性 (===) 比較不穩定參數
  • 系統會使用物件相等性 (Object.equals()) 比較穩定參數

如果所有參數都符合這些要求,Compose 會在重組期間略過可組合項。

您可能會希望可組合項選擇不採用強制略過功能。也就是說,您可能需要可重新啟動但不可略過的可組合項。在這種情況下,請使用 @NonSkippableComposable 註解。

@NonSkippableComposable
@Composable
fun MyNonSkippableComposable {}

將類別標示為穩定

如果您希望物件使用物件相等性,而非執行個體相等性,請繼續使用 @Stable 為指定類別加上註解。舉例來說,如果您要觀察整個物件清單,就必須這樣做,因為 Room 等資料來源會在清單中的某個項目發生變更時,為清單中的每個項目分配新的物件。

Lambda 備忘功能

嚴格略過模式還可在可組合項中提供更多 memoization 的 lambda。啟用嚴格略過模式後,可組合函式內的每個 lambda 都會自動記住。

範例

為了在使用強制略過功能時,在可組合函式中實現 lambda 的快取,編譯器會使用 remember 呼叫包裝 lambda。並以 lambda 的擷取項目做為索引。

請考慮下列 lambda 的情況:

@Composable
fun MyComposable(unstableObject: Unstable, stableObject: Stable) {
    val lambda = {
        use(unstableObject)
        use(stableObject)
    }
}

啟用嚴格略過功能後,編譯器會在 remember 呼叫中包裝 lambda,以便記錄 lambda:

@Composable
fun MyComposable(unstableObject: Unstable, stableObject: Stable) {
    val lambda = remember(unstableObject, stableObject) {
        {
            use(unstableObject)
            use(stableObject)
        }
    }
}

鍵會遵循與可組合函式相同的比較規則。執行階段會使用例項相等性比較不穩定的鍵。它會使用物件相等性比較穩定的鍵。

備忘符號和重組

這項最佳化功能可大幅增加執行階段在重組期間略過的可組合項數量。在沒有 memoization 的情況下,執行階段更有可能將新 lambda 分配給在重組期間接受 lambda 參數的任何可組合項。因此,新 lambda 的參數與上一個組合不相等。這會導致重組。

避免 memoization

如果您有一個不想儲存的 lambda,請使用 @DontMemoize 註解。

val lambda = @DontMemoize {
    ...
}

APK 大小

在編譯時,可略過的可組合項會產生比不可略過的可組合項更多的程式碼。啟用強制略過功能後,編譯器會將幾乎所有可組合項標示為可略過,並將所有 lambda 包裝在 remember{...} 中。因此,啟用嚴格略過模式對應用程式 APK 大小的影響非常小。

Now In Android 中啟用強制略過功能,會使 APK 大小增加 4 kB。大小差異主要取決於先前在特定應用程式中出現的不可略過可組合函式數量,但應該會相對較小。