強式略過模式

「強式略過」是 Compose 編譯器中的模式。啟用後,系統會以兩種方式變更編譯器的行為:

  • 含有不穩定的參數的可組合項會可略過
  • 系統會記住含有無法拍攝的 Lambda

啟用嚴格略過模式

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

android { ... }

composeCompiler {
   enableStrongSkippingMode = true
}

可組合項的可略過性設定

在略過和可組合函式方面,強式略過模式會放寬 Compose 編譯器一般套用的部分「穩定性」規則。根據預設,如果可組合函式的所有引數都有穩定的值,Compose 編譯器會將該可組合函式標示為可略過。強勢略過模式會改變這種情況。

啟用強式略過功能時,所有可重新啟動的可組合函式都會變為略過狀態。無論參數是否不穩定,都會發生這個情況。無法重新啟動的可組合函式仍然無法略過。

略過時機

為了判斷在重組期間是否略過某個可組合項,Compose 會比較每個參數的值與先前的值。比較類型取決於參數的 stability

  • 系統會使用執行個體等式 (===) 比較不穩定的參數
  • 系統會使用物件等式 (Object.equals()) 比較穩定版參數

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

您可能會希望可組合項停用強式略過功能。這代表您可能需要可重新啟動但不可略過的可組合項。在這種情況下,請使用 @NonSkippableComposable 註解。

@NonSkippableComposable
@Composable
fun MyNonSkippableComposable {}

為類別加上註解

如要讓物件使用物件等式 (而非執行個體相等),請繼續使用 @Stable 為指定類別加註。可能必須執行這項操作的例子,就是觀察整個物件清單時,Room 等資料來源會在每次變更時,為清單中的每個項目分配新物件。

Lambda 記憶

強式略過模式還能在可組合項內提供更多 lambda 的記憶。啟用強式略過後,系統會自動記住可組合函式中的每個 lambda。

示例

為了在使用強式略過功能時在可組合項中留下 lambda 的記憶,編譯器會使用 remember 呼叫納入 lambda。這個索引鍵是由 lambda 擷取而成。

假設您有一個 lambda,範例如下:

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

啟用強式略過後,編譯器會將 lambda 納入 remember 呼叫中,藉此記憶 lambda:

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

這些鍵遵循與可組合函式相同的比較規則。執行階段會使用執行個體相等性來比較不穩定的金鑰。它會使用物件相等性來比較穩定鍵。

記憶與重新組成

這項最佳化功能會大幅增加執行階段在重組期間略過的可組合項數量。如果沒有節錄,執行階段更有可能將新的 lambda 分配給在重組期間接受 lambda 參數的任何可組合項。因此,新 lambda 的參數與最後一個組合不同。這樣就會造成重組。

避免記憶

如果您不想記下 lambda,請使用 @DontMemoize 註解。

val lambda = @DontMemoize {
    ...
}

APK 大小

編譯時,可略過的可組合項產生的程式碼比不可略過的可組合項多。啟用強式略過後,編譯器會將幾乎所有可組合項標示為可略過,並將所有 lambda 納入 remember{...} 中。因此,啟用高強度略過模式對應用程式的 APK 大小的影響微乎其微。

Now In Android 中啟用高強度略過功能,APK 大小增加了 4 KB。大小差異主要取決於特定應用程式中先前不可略過的可組合項數量,但應該相對較小。