Lebenszyklus von zusammensetzbaren Funktionen

Auf dieser Seite erfahren Sie mehr über den Lebenszyklus einer zusammensetzbaren Funktion wie Compose entscheidet, ob eine zusammensetzbare Funktion neu zusammengesetzt werden muss.

Lebenszyklusübersicht

Wie in der Dokumentation zur Statusverwaltung erwähnt, ist ein Zusammensetzung beschreibt die Benutzeroberfläche Ihrer App und wird durch das Ausführen von zusammensetzbaren Funktionen erstellt. Eine Komposition ist eine Baumstruktur der zusammensetzbaren Funktionen, die Ihre Benutzeroberfläche beschreiben.

Wenn Jetpack Compose Ihre zusammensetzbaren Funktionen zum ersten Mal ausführt, während für den Anfang Zusammensetzung, erfasst sie die zusammensetzbaren Funktionen, die Sie zur Beschreibung in einer Komposition. Wenn sich der Status Ihrer App ändert, Beim Erstellen wird eine Neuzusammensetzung geplant. Die Neuzusammensetzung erfolgt bei Jetpack Compose die zusammensetzbaren Funktionen, die sich als Reaktion auf Statusänderungen geändert haben, und aktualisiert dann die Komposition bei Änderungen.

Eine Komposition kann nur durch eine ursprüngliche Komposition produziert und von Neuzusammensetzung. Eine Komposition kann nur durch Neuzusammensetzung geändert werden.

Diagramm, das den Lebenszyklus einer zusammensetzbaren Funktion zeigt

Abbildung 1: Lebenszyklus einer zusammensetzbaren Funktion in der Zusammensetzung Sie taucht in die Komposition, wird 0-mal oder öfter neu zusammengesetzt und verlässt die Komposition.

Die Neuzusammensetzung wird in der Regel durch eine Änderung an einer State<T>-Objekt. Verfassen verfolgt sie und führt alle zusammensetzbaren Funktionen in der Komposition aus, die Folgendes lautet: bestimmte State<T> sowie alle zusammensetzbaren Funktionen, die sie aufrufen und die nicht übersprungen.

Wird eine zusammensetzbare Funktion mehrmals aufgerufen, werden mehrere Instanzen im Komposition Jeder Aufruf hat in der Zusammensetzung seinen eigenen Lebenszyklus.

@Composable
fun MyComposable() {
    Column {
        Text("Hello")
        Text("World")
    }
}

Diagramm, das die hierarchische Anordnung der Elemente im vorherigen Code-Snippet zeigt

Abbildung 2: Darstellung von MyComposable in der Komposition. Wenn ein wird mehrfach aufgerufen, werden mehrere Instanzen im Komposition Ein Element mit einer anderen Farbe weist darauf hin, eine separate Instanz erstellen.

Anatomie einer Zusammensetzung in einer Komposition

Die Instanz einer zusammensetzbaren Funktion in der Komposition wird durch die entsprechende Aufrufwebsite identifiziert. Der Compose-Compiler betrachtet jede Aufruf-Website als eigenständige Website. Zusammensetzbare Funktionen aufrufen Aufruf-Websites erstellen, werden mehrere Instanzen der zusammensetzbaren Funktion in Komposition

Wenn eine zusammensetzbare Funktion während einer Neuzusammensetzung andere zusammensetzbare Funktionen aufruft vorherigen Kompositionen ermittelt, um zu bestimmen, welche zusammensetzbaren Funktionen aufgerufen oder nicht aufgerufen, sowie für die zusammensetzbaren Funktionen, die in beiden Kompositionen vermeidet, vermeidet die Funktion "Compose" eine Neuzusammensetzung, geändert.

Die Bewahrung der Identität ist entscheidend, um Nebenwirkungen mit damit sie erfolgreich abgeschlossen werden können und nicht nach jedem Neustart neu gestartet werden müssen. Neuzusammensetzung.

Betrachten Sie das folgende Beispiel:

@Composable
fun LoginScreen(showError: Boolean) {
    if (showError) {
        LoginError()
    }
    LoginInput() // This call site affects where LoginInput is placed in Composition
}

@Composable
fun LoginInput() { /* ... */ }

@Composable
fun LoginError() { /* ... */ }

Im obigen Code-Snippet ruft LoginScreen bedingt die Methode LoginError zusammensetzbar und ruft immer die zusammensetzbare LoginInput auf. Jedes -Aufruf hat eine eindeutige Aufrufwebsite und Quellposition, die vom Compiler verwendet werden, um eindeutig identifiziert werden.

Diagramm, das zeigt, wie der vorherige Code neu zusammengesetzt wird, wenn das Flag showError in „true“ geändert wird. Die zusammensetzbare Funktion „LoginError“ wird hinzugefügt, die anderen zusammensetzbaren Funktionen jedoch nicht.

Abbildung 3: Darstellung von LoginScreen in der Komposition, wenn der Zustand und es findet eine Neuzusammensetzung statt. Die gleiche Farbe bedeutet, dass es nicht neu zusammengesetzt wurde.

LoginInput wurde zwar statt der ersten zu einer zweiten, aber Die Instanz LoginInput wird bei allen Neuzusammensetzungen beibehalten. Außerdem weil es bei LoginInput keine Parameter gibt, die sich im Laufe der Zeit Neuzusammensetzung ist, wird der Aufruf von LoginInput mit der Funktion "Compose" übersprungen.

Zusätzliche Informationen für eine intelligente Neuzusammensetzung hinzufügen

Durch mehrfaches Aufrufen einer zusammensetzbaren Funktion wird sie mehrfach als gut. Wenn Sie eine zusammensetzbare Funktion mehrmals von derselben Aufruf-Website aufrufen, verwenden Sie die Funktion keine Informationen zur eindeutigen Identifizierung der Aufrufe der zusammensetzbaren Funktion hat, Die Ausführungsreihenfolge wird daher zusätzlich zur Aufrufwebsite verwendet, Instanzen unterschiedlich sind. Manchmal reicht dieses Verhalten aus, kann es unerwünschtes Verhalten verursachen.

@Composable
fun MoviesScreen(movies: List<Movie>) {
    Column {
        for (movie in movies) {
            // MovieOverview composables are placed in Composition given its
            // index position in the for loop
            MovieOverview(movie)
        }
    }
}

Im obigen Beispiel verwendet Compose zusätzlich zum Aufruf auch die Ausführungsreihenfolge. um die Instanz in der Komposition eindeutig zu machen. Wenn eine neue movie hinzugefügt wird unten der Liste können Sie mit der Funktion "Compose" die Instanzen wiederverwenden, die bereits in der Da sich die Zusammensetzung in der Liste nicht geändert hat, Die movie-Eingabe ist für diese Instanzen gleich.

Diagramm, das zeigt, wie der vorherige Code neu zusammengesetzt wird, wenn am Ende der Liste ein neues Element hinzugefügt wird. Die anderen Elemente in der Liste haben ihre Position nicht geändert und werden nicht neu zusammengesetzt.

Abbildung 4: Darstellung von MoviesScreen in der Komposition, wenn eine neue wird am Ende der Liste hinzugefügt. MovieOverview zusammensetzbare Funktionen in der Zusammensetzung kann wiederverwendet werden. Die gleiche Farbe in MovieOverview bedeutet, dass die zusammensetzbare Funktion nicht neu zusammengesetzt wurde.

Ändert sich die movies-Liste jedoch entweder durch Hinzufügen zum top-Wert oder zum Mitte der Liste entfernt oder Elemente neu angeordnet werden, führt das zu einer Neuzusammensetzung, bei allen MovieOverview-Aufrufen, deren Eingabeparameter sich die Position im Liste. Das ist zum Beispiel sehr wichtig, wenn MovieOverview Filmbild mit einem Nebeneffekt hinzu. Wenn es zu einer Neuzusammensetzung kommt, während der Effekt auftritt abgeschlossen haben, wird er abgebrochen und neu gestartet.

@Composable
fun MovieOverview(movie: Movie) {
    Column {
        // Side effect explained later in the docs. If MovieOverview
        // recomposes, while fetching the image is in progress,
        // it is cancelled and restarted.
        val image = loadNetworkImage(movie.url)
        MovieHeader(image)

        /* ... */
    }
}

Diagramm, das zeigt, wie der vorherige Code neu zusammengesetzt wird, wenn ein neues Element an den Anfang der Liste gesetzt wird. Jedes andere Element in der Liste ändert die Position und muss neu zusammengesetzt werden.

Abbildung 5: Darstellung von MoviesScreen in der Komposition, wenn eine neue wird der Liste hinzugefügt. Zusammensetzbare MovieOverview-Elemente können nicht wiederverwendet und werden alle Nebenwirkungen neu gestartet. Eine andere Farbe in MovieOverview bedeutet, dass das zusammensetzbar ist, wurde neu zusammengesetzt.

Idealerweise sollten wir uns die Identität der MovieOverview-Instanz mit der Identität der movie verknüpft ist, die an sie übergeben wird. Wenn wir die Spalten Idealerweise würden wir die Instanzen im Feld Zusammensetzungsbaum, anstatt jede zusammensetzbare Funktion MovieOverview mit einem eine andere Filminstanz. Mit dem Befehl „Compose“ können Sie die Laufzeit welche Werte Sie verwenden möchten, um einen bestimmten Teil der Baumstruktur zu identifizieren: die key zusammensetzbar.

Durch das Umschließen eines Codeblocks mit einem Aufruf an den Schlüssel, der mit einem oder mehreren übergebene Werte werden kombiniert, um zu ermitteln, -Instanz in der Komposition. Der Wert für key muss nicht global eindeutig sein darf, darf sie nur unter den Aufrufen von zusammensetzbaren Funktionen auf der Call-Site verwenden. In diesem Beispiel muss also jede movie einen key, das unter den movies eindeutig ist. können Sie diese key mit anderen Nutzern teilen, weitere zusammensetzbare Funktionen an anderer Stelle in der App.

@Composable
fun MoviesScreenWithKey(movies: List<Movie>) {
    Column {
        for (movie in movies) {
            key(movie.id) { // Unique ID for this movie
                MovieOverview(movie)
            }
        }
    }
}

Die Funktion „Schreiben“ erkennt einzelne Aufrufe an MovieOverview und können diese wiederverwenden.

Diagramm, das zeigt, wie der vorherige Code neu zusammengesetzt wird, wenn ein neues Element an den Anfang der Liste gesetzt wird. Da die Listenelemente durch Schlüssel gekennzeichnet sind, weiß Compose nicht, dass sie neu zusammengesetzt werden müssen, auch wenn sich ihre Positionen geändert haben.

Abbildung 6: Darstellung von MoviesScreen in der Komposition, wenn eine neue wird der Liste hinzugefügt. Da die zusammensetzbaren Funktionen von MovieOverview eindeutige erkennt Compose, welche MovieOverview Instanzen unverändert sind, und sie wiederverwenden; dass ihre Nebenwirkungen weiterhin ausgeführt werden.

Einige zusammensetzbare Funktionen unterstützen die zusammensetzbare Funktion key. Beispiel: LazyColumn akzeptiert die Angabe einer benutzerdefinierten key in items DSL.

@Composable
fun MoviesScreenLazy(movies: List<Movie>) {
    LazyColumn {
        items(movies, key = { movie -> movie.id }) { movie ->
            MovieOverview(movie)
        }
    }
}

Überspringen, wenn sich die Eingaben nicht geändert haben

Bei der Neuzusammensetzung können einige zusammensetzbare Funktionen ihre die Ausführung vollständig übersprungen, wenn sich ihre Eingaben im Vergleich zur vorherigen nicht geändert haben. Zusammensetzung.

Eine zusammensetzbare Funktion kann übersprungen werden, außer

  • Die Funktion hat einen Rückgabetyp, der nicht Unit ist
  • Die Funktion ist mit @NonRestartableComposable oder @NonSkippableComposable
  • Ein erforderlicher Parameter ist ein instabiler Typ.

Es gibt den experimentellen Compiler-Modus Strong Skipping. wodurch die letzte Anforderung gelockert wird.

Damit ein Typ als stabil gilt, muss er folgende Anforderungen erfüllen: Vertrag:

  • Das Ergebnis von equals für zwei Instanzen ist immer das gleiche für die dieselben zwei Instanzen.
  • Wenn sich ein öffentliches Eigentum dieses Typs ändert, wird die Komposition benachrichtigt.
  • Alle Arten öffentlicher Immobilien sind ebenfalls unverändert.

Es gibt einige wichtige gängige Arten, die in diesen Vertrag fallen, Der Compose-Compiler wird als stabil behandelt, auch wenn er nicht explizit mit der Anmerkung @Stable als stabil markiert:

  • Alle primitiven Werttypen: Boolean, Int, Long, Float, Char usw.
  • Strings
  • Alle Funktionstypen (Lambdas)

Für alle diese Typen gilt ein stabiler Vertrag, unveränderlich. Da unveränderliche Typen sich nie ändern, müssen sie nie benachrichtigt werden. Zusammensetzung der Änderung, sodass es viel einfacher ist, diesen Vertrag einzuhalten.

Ein bemerkenswerter Typ, der stabil ist, aber änderbar ist, ist MutableState Typ. Wenn ein Wert in einem MutableState enthalten ist, ist das Statusobjekt insgesamt gilt als stabil, da Compose über alle Änderungen am .value-Eigenschaft von State.

Wenn alle Typen, die als Parameter an eine zusammensetzbare Funktion übergeben werden, stabil sind, wird der Parameter werden die Werte anhand der zusammensetzbaren Position in der Benutzeroberfläche auf Gleichheit geprüft. Baum. Die Neuzusammensetzung wird übersprungen, wenn alle Werte seit dem vorherigen Anruf.

Compose betrachtet einen Typ nur dann als stabil, wenn er dies nachweisen kann. Beispiel: wird im Allgemeinen als instabil behandelt und es werden Typen mit änderbaren öffentlichen Properties, deren Implementierung möglicherweise unveränderlich sein könnte, sind ebenfalls nicht stabil.

Wenn mit „Compose“ nicht ermittelt werden kann, ob ein Typ stabil ist, Sie aber erzwingen möchten, Compose, um ihn als stabil zu behandeln, markieren Sie ihn mit dem @Stable-Anmerkung.

// Marking the type as stable to favor skipping and smart recompositions.
@Stable
interface UiState<T : Result<T>> {
    val value: T?
    val exception: Throwable?

    val hasError: Boolean
        get() = exception != null
}

Da es sich bei UiState um eine Benutzeroberfläche handelt, wird dieser Typ üblicherweise als nicht stabil erachtet. Durch Hinzufügen der @Stable kennzeichnen Sie Compose, dass dieser Typ stabil ist, sodass "Compose" bevorzugt kluge Neuzusammensetzungen. Das bedeutet auch, dass die Funktion "Compose" alle Implementierungen als stabil, wenn das Interface als Parametertyp verwendet wird.