Wenn Sie mit einer instabilen Klasse konfrontiert werden, die Leistung verursacht sollte es stabil sein. In diesem Dokument werden mehrere Techniken beschrieben, verwenden können.
Starkes Überspringen aktivieren
Du solltest zuerst versuchen, den starken Überspringenmodus zu aktivieren. Starker Überspringen-Modus ermöglicht das Überspringen von zusammensetzbaren Funktionen mit instabilen Parametern und ist die Methode, um durch Stabilität verursachte Leistungsprobleme zu beheben.
Weitere Informationen finden Sie unter Starkes Überspringen.
Klasse unveränderlich machen
Sie können auch versuchen, eine instabile Klasse vollständig unveränderlich zu machen.
- Unveränderlich: Gibt einen Typ an, bei dem der Wert eines Attributs niemals
sich nach dem Erstellen einer Instanz dieses Typs ändern, und alle Methoden sind
referenzieren transparent sind.
- Achten Sie darauf, dass alle Attribute der Klasse
val
und nichtvar
sind. und unveränderlichen Typen. - Einfache Typen wie
String, Int
undFloat
sind immer unveränderlich. - Sollte dies nicht möglich sein, müssen Sie den Erstellungsstatus für alle änderbaren Attribute.
- Achten Sie darauf, dass alle Attribute der Klasse
- Stabil: Gibt einen Typ an, der änderbar ist. Die Compose-Laufzeit werden, ob und wann öffentliche Attribute oder Methoden führt zu anderen Ergebnissen als ein vorheriger Aufruf.
Unveränderliche Sammlungen
Ein häufiger Grund, warum Compose eine Klasse als instabil einstuft, sind Sammlungen. Wie erwähnt
auf der Seite Stabilitätsprobleme diagnostizieren den Compiler
kann nicht sicher sein, dass Sammlungen wie List, Map
und Set
sind sie wirklich unveränderlich
und werden daher als instabil markiert.
Um dieses Problem zu beheben, können Sie unveränderliche Sammlungen verwenden. Compiler „Compose“ Kotlinx Unmutable Collections wird unterstützt. Diese Sammlungen sind garantiert unveränderlich und werden vom Compose-Compiler behandelt. als solches. Diese Bibliothek befindet sich noch in der Alphaphase, daher sind Änderungen an ihrer API zu erwarten.
Diese instabile Klasse aus der Spalte Stabilität diagnostizieren Leitfaden zu Problemen:
unstable class Snack {
…
unstable val tags: Set<String>
…
}
Sie können tags
mit einer unveränderlichen Sammlung stabil machen. Ändern Sie im Kurs
Typ von tags
in ImmutableSet<String>
:
data class Snack{
…
val tags: ImmutableSet<String> = persistentSetOf()
…
}
Danach sind alle Parameter der Klasse unveränderlich und der Befehl "Compose" markiert die Klasse als stabil.
Mit Stable
oder Immutable
annotieren
Sie können Stabilitätsprobleme beheben, indem Sie instabile Klassen mit Anmerkungen versehen.
entweder mit @Stable
oder @Immutable
.
Durch das Annotieren einer Klasse wird das überschrieben, was der Compiler sonst vornehmen würde.
Ihre Klasse ableiten. Es ähnelt dem
Der Operator !!
in Kotlin Sie sollten sehr
wie Sie diese Anmerkungen verwenden. Compilerverhalten überschreiben
kann es zu unerwarteten Fehlern kommen, z. B. dass Ihre zusammensetzbare Funktion nicht
die Sie erwarten.
Wenn es möglich ist, Ihre Klasse ohne Anmerkung stabil zu gestalten, sollten Sie auf diese Weise Stabilität zu erreichen.
Das folgende Snippet zeigt ein minimales Beispiel für eine Datenklasse, die wie folgt annotiert ist: unveränderlich:
@Immutable
data class Snack(
…
)
Unabhängig davon, ob Sie die Annotation @Immutable
oder @Stable
verwenden,
kennzeichnet die Snack
-Klasse als stabil.
Mit Anmerkungen versehene Klassen in Sammlungen
Sehen wir uns eine zusammensetzbare Funktion an, die einen Parameter vom Typ List<Snack>
enthält:
restartable scheme("[androidx.compose.ui.UiComposable]") fun HighlightedSnacks(
…
unstable snacks: List<Snack>
…
)
Auch wenn Sie Snack
mit @Immutable
annotieren, markiert der Compose-Compiler weiterhin
snacks
-Parameter in HighlightedSnacks
als instabil.
Parameter haben bei Sammlungstypen das gleiche Problem wie Klassen.
Der Compose-Compiler markiert immer einen Parameter des Typs List
als instabil, sogar
wenn es sich um eine Sammlung stabiler Typen handelt.
Sie können weder einzelne Parameter als stabil markieren zusammensetzbar sind, damit sie immer überspringbar sind. Es gibt mehrere Wege vorwärts.
Es gibt mehrere Möglichkeiten, das Problem instabiler Sammlungen zu umgehen. In den folgenden Unterabschnitten werden diese Ansätze erläutert.
Konfigurationsdatei
Wenn Sie sich an den Stabilitätsvertrag in Ihrer Codebasis halten,
können Sie Kotlin-Sammlungen als stabil erwägen, indem Sie
kotlin.collections.*
zu deinem
Konfigurationsdatei für Stabilität.
Unveränderliche Sammlung
Zur Sicherheit der Unveränderlichkeit für die Kompilierungszeit können Sie
Verwenden Sie statt List
eine unveränderliche Kotlinx-Sammlung.
@Composable
private fun HighlightedSnacks(
…
snacks: ImmutableList<Snack>,
…
)
Wrapper
Wenn Sie eine unveränderliche Sammlung nicht verwenden können, können Sie Ihre eigene erstellen. Gehen Sie dazu wie folgt vor:
die List
in eine annotierte stabile Klasse verpacken. Ein generischer Wrapper ist wahrscheinlich
die beste Wahl dafür ist.
@Immutable
data class SnackCollection(
val snacks: List<Snack>
)
Diesen können Sie dann als Parametertyp in Ihrer zusammensetzbaren Funktion verwenden.
@Composable
private fun HighlightedSnacks(
index: Int,
snacks: SnackCollection,
onSnackClick: (Long) -> Unit,
modifier: Modifier = Modifier
)
Lösung
Nachdem Sie einen dieser Ansätze gewählt haben, markiert der Compose-Compiler jetzt den
HighlightedSnacks
Zusammensetzbar als skippable
und 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
)
Beim Neuzusammensetzen kann HighlightedSnacks
jetzt übersprungen werden, wenn keine
Eingaben geändert.
Konfigurationsdatei für die Stabilität
Beginnend mit Compose Compiler 1.5.5, einer Konfigurationsdatei mit Klassen,
stabil kann bei der Kompilierung bereitgestellt werden. So können Sie sich überlegen,
Klassen, die Sie nicht steuern, z. B. Standardbibliotheksklassen
wie LocalDateTime
als stabil.
Die Konfigurationsdatei ist eine Nur-Text-Datei mit einer Klasse pro Zeile. Kommentare, einfache und doppelte Platzhalter unterstützt werden. Im Folgenden finden Sie eine Beispielkonfiguration:
// 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<*,_>
Um diese Funktion zu aktivieren, übergeben Sie den Pfad der Konfigurationsdatei an das Compiler-Optionen.
Cool
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"
)
}
Da der Compose-Compiler für jedes Modul in Ihrem Projekt separat ausgeführt wird, können Sie bei Bedarf unterschiedliche Konfigurationen für verschiedene Module bereitstellen. Alternativ haben Sie die Möglichkeit, die Konfiguration auf der Stammebene Ihres Projekts aus und übergeben Sie diesen Pfad an jede -Modul.
Mehrere Module
Ein weiteres häufiges Problem betrifft die Architektur mit mehreren Modulen. Compiler „Compose“ kann nur ableiten, ob eine Klasse stabil ist, wenn alle nicht-primitiven Typen, die Referenzen sind entweder explizit als stabil gekennzeichnet oder in einem Modul, auch mit dem Compose-Compiler erstellt.
Befindet sich die Datenschicht in einem anderen Modul als der UI-Ebene, empfohlenen Lösungsansatz, könnte es ein Problem sein, das bei Ihnen auftritt.
Lösung
Dieses Problem lässt sich mit einer der folgenden Methoden beheben:
- Fügen Sie die Klassen der Compiler-Konfigurationsdatei hinzu.
- Aktivieren Sie den Compiler Compose in Ihren Datenschichtmodulen oder taggen Sie Ihre Klassen
gegebenenfalls mit
@Stable
oder@Immutable
.- Dazu muss der Datenschicht eine Schreibabhängigkeit hinzugefügt werden. Sie können jedoch
Es handelt sich nur um die Abhängigkeit für die Compose-Laufzeit, nicht für
Compose-UI
- Dazu muss der Datenschicht eine Schreibabhängigkeit hinzugefügt werden. Sie können jedoch
Es handelt sich nur um die Abhängigkeit für die Compose-Laufzeit, nicht für
- Binden Sie die Datenschichtklassen im UI-Modul in einen UI-spezifischen Wrapper ein. Klassen.
Das gleiche Problem tritt auch auf, wenn externe Bibliotheken verwendet werden, wenn diese nicht die Compiler erstellen.
Nicht jede zusammensetzbare Funktion sollte überspringbar sein.
Wenn Sie Stabilitätsprobleme beheben, sollten Sie nicht versuchen, zusammensetzbar, überspringbar. Ein solcher Versuch kann zu einer vorzeitigen Optimierung führen bringt mehr Probleme mit sich, als sie behoben werden.
Es gibt viele Situationen, in denen überspringbare Anzeigen keine nennenswerten Vorteile haben. und den Code zu verwalten. Beispiel:
- Eine zusammensetzbare Funktion, die nicht oft oder überhaupt neu zusammengesetzt wird.
- Eine zusammensetzbare Funktion, die allein als „überspringbare zusammensetzbare Funktionen“ bezeichnet wird.
- Zusammensetzbare Funktion mit einer großen Anzahl von Parametern und teuren Gleichheitszeichen Implementierungen. In diesem Fall werden die Kosten für die Prüfung, ob einer der Parameter die Kosten einer billigen Neuzusammensetzung überwiegen können.
Wenn eine zusammensetzbare Funktion überspringbar ist, entsteht ein geringer Mehraufwand, der sich vielleicht nicht lohnen würde. . Sie haben sogar die Möglichkeit, die zusammensetzbare Funktion so zu kennzeichnen, dass sie in Fällen nicht wieder gestartet werden kann. dass ein Neustart mehr Aufwand verursacht, als er wert ist.