強式略過模式

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

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

啟用嚴格略過模式

如要為先前版本的 Gradle 模組啟用嚴格略過功能,請在 Gradle 設定的 composeCompiler 區塊中加入下列選項:

android { ... }

composeCompiler {
   enableStrongSkippingMode = true
}

可組合函式可略過性

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

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

何時可略過

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

  • 系統會透過例項相等性 (===) 比較不穩定的參數
  • 系統會使用物件相等性 (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)
        }
    }
}

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

記憶和重新組合

這項最佳化功能可大幅增加執行階段在重組期間略過的可組合項數量。如果沒有記憶功能,執行階段會更有可能將新的 lambda 配置到在重組期間使用 lambda 參數的任何可組合項。因此,新 lambda 的參數與上一個組合不相等。這會導致重組。

避免 memoization

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

val lambda = @DontMemoize {
    ...
}

APK 大小

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

Now In Android 中啟用強制略過功能,會使 APK 大小增加 4 kB。大小差異主要取決於特定應用程式中先前無法略過的可組合項數量,但應相對輕微。