Starker Sprungmodus

Strong Skipping ist ein Modus, der im Compose-Compiler verfügbar ist. Wenn diese Option aktiviert ist, ändert sich das Verhalten des Compilers auf zwei Arten:

  • Komponierbare Funktionen mit instabilen Parametern werden überspringbar.
  • Lambdas mit instabilen Erfassungen werden gespeichert.

Modus für starkes Überspringen aktivieren

In Kotlin 2.0.20 ist das starke Überspringen standardmäßig aktiviert.

Wenn Sie das strenge Überspringen für ein Gradle-Modul in einer Version vor 2.0.20 aktivieren möchten, fügen Sie die folgende Option in den composeCompiler-Block Ihrer Gradle-Konfiguration ein:

android { ... }

composeCompiler {
   enableStrongSkippingMode = true
}

Überspringbarkeit von Composable-Funktionen

Im Modus „Starkes Überspringen“ werden einige der Stabilitätsregeln gelockert, die der Compose-Compiler normalerweise beim Überspringen und bei zusammensetzbaren Funktionen anwendet. Standardmäßig markiert der Compose-Compiler eine zusammensetzbare Funktion als überspringbar, wenn alle ihre Argumente stabile Werte haben. Der Modus „Starkes Überspringen“ ändert dies.

Wenn das starke Überspringen aktiviert ist, können alle neustartbaren zusammensetzbaren Funktionen übersprungen werden. Dies gilt unabhängig davon, ob sie instabile Parameter haben oder nicht. Nicht neu startbare zusammensetzbare Funktionen können weiterhin nicht übersprungen werden.

Wann überspringen?

Um festzustellen, ob eine zusammensetzbare Funktion bei der Neuzusammensetzung übersprungen werden soll, vergleicht Compose den Wert jedes Parameters mit den vorherigen Werten. Die Art des Vergleichs hängt von der Stabilität des Parameters ab.

  • Instabile Parameter werden mithilfe der Instanzgleichheit (===) verglichen.
  • Stabile Parameter werden mithilfe der Objektgleichheit (Object.equals()) verglichen.

Wenn alle Parameter diese Anforderungen erfüllen, überspringt Compose die zusammensetzbare Funktion während der Neuzusammensetzung.

Möglicherweise möchten Sie, dass eine zusammensetzbare Funktion nicht für das Strong Skipping verwendet wird. Das heißt, Sie möchten möglicherweise eine neustartbare, aber nicht überspringbare zusammensetzbare Funktion. Verwenden Sie in diesem Fall die Annotation @NonSkippableComposable.

@NonSkippableComposable
@Composable
fun MyNonSkippableComposable {}

Klassen als stabil annotieren

Wenn Sie möchten, dass ein Objekt anhand der Objektgleichheit (Object.equals()) anstelle der Instanzgleichheit (===) verglichen wird, annotieren Sie die entsprechende Klasse weiterhin mit @Stable oder @Immutable.

Beachten Sie die folgenden Vor- und Nachteile, bevor Sie @Stable oder @Immutable hinzufügen:

  • Klassen mit stabilen Properties in Compose-Modulen sind bereits stabil: Eine Klasse mit val-Properties stabiler Typen in einem Modul, das mit dem Compose-Compiler kompiliert wurde, wird automatisch als stabil eingestuft und verwendet .equals(), ohne dass @Immutable oder @Stable erforderlich sind.
  • Klassen nur mit kostengünstigen .equals()-Prüfungen annotieren: Fügen Sie @Stable oder @Immutable hinzu, wenn der Compiler die Stabilität nicht ableiten kann (z. B. Klassen aus Nicht-Compose-Modulen) und häufig neue Instanzen mit identischen Werten zugewiesen werden, sofern die .equals()-Prüfung der Klasse kostengünstig ist.
  • Seien Sie vorsichtig, wenn Sie Modelle mit Sammlungen annotieren: Wenn Sie @Stable oder @Immutable zu Modellen hinzufügen, die Sammlungen enthalten (oder List durch ImmutableList ersetzen), vergleicht Compose bei jeder Neuzusammensetzung jedes Element in der Sammlung mit .equals(). Bei großen Sammlungen oder Modellen, die in Lazy Layouts (LazyColumn, LazyRow, LazyGrid) verwendet werden, kann der Vergleich jedes Elements langsamer sein als die Verwendung der Instanzgleichheit (===) oder die direkte Neuzusammensetzung.

Lambda-Memoisierung

Der Modus „Starkes Überspringen“ ermöglicht auch eine stärkere Memoisierung von Lambdas in Composables. Wenn das starke Überspringen aktiviert ist, wird jedes Lambda in einer zusammensetzbaren Funktion automatisch gespeichert.

Beispiele

Damit Lambdas in Composables bei Verwendung des strikten Überspringens gespeichert werden, umschließt der Compiler das Lambda mit einem remember-Aufruf. Sie wird mit den Erfassungen des Lambda-Ausdrucks verschlüsselt.

Angenommen, Sie haben eine Lambda-Funktion wie im folgenden Beispiel:

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

Wenn das strenge Überspringen aktiviert ist, speichert der Compiler den Lambda-Ausdruck, indem er ihn in einen remember-Aufruf einbindet:

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

Für die Schlüssel gelten dieselben Vergleichsregeln wie für zusammensetzbare Funktionen. Die Laufzeit vergleicht instabile Schlüssel anhand der Instanzgleichheit. Stabile Schlüssel werden anhand der Objektgleichheit verglichen.

Memoization und Neuzusammensetzung

Durch diese Optimierung wird die Anzahl der Composables, die die Laufzeit während der Neuzusammensetzung überspringt, erheblich erhöht. Ohne Memoisierung ist es viel wahrscheinlicher, dass die Laufzeit jedem Compose-Objekt, das während der Neuzusammensetzung einen Lambda-Parameter akzeptiert, ein neues Lambda zuweist. Daher hat die neue Lambda-Funktion Parameter, die nicht mit der letzten Zusammensetzung übereinstimmen. Dies führt zu einer Neuzusammensetzung.

Memoisation vermeiden

Wenn Sie eine Lambda-Funktion haben, die Sie nicht memoizen möchten, verwenden Sie die Annotation @DontMemoize.

val lambda = @DontMemoize {
    ...
}

APK-Größe

Beim Kompilieren führen überspringbare Composables zu mehr generiertem Code als nicht überspringbare Composables. Wenn das starke Überspringen aktiviert ist, markiert der Compiler fast alle Composables als überspringbar und verpackt alle Lambdas in ein remember{...}. Daher hat die Aktivierung des Modus „Starkes Überspringen“ nur sehr geringe Auswirkungen auf die APK-Größe Ihrer Anwendung.

Durch die Aktivierung des starken Überspringens in Now In Android hat sich die APK-Größe um 4 KB erhöht. Der Größenunterschied hängt weitgehend von der Anzahl der zuvor nicht überspringbaren Composables in der jeweiligen App ab, sollte aber relativ gering sein.