Der Status in einer App ist jeder Wert, der sich im Laufe der Zeit ändern kann. Dies ist eine sehr allgemeine und umfasst alles von einer Room-Datenbank bis hin zu .
Der Status aller Android-Apps wird dem Nutzer angezeigt. Einige Beispiele für Status in Android Apps:
- Eine Snackbar, die anzeigt, wenn keine Netzwerkverbindung hergestellt werden kann.
- Ein Blogpost und zugehörige Kommentare.
- Wellenförmige Animationen auf Schaltflächen, die abgespielt werden, wenn ein Nutzer darauf klickt.
- Sticker, die Nutzende auf einem Bild zeichnen können.
Mit Jetpack Compose kannst du genau angeben, wo und wie du sie speicherst und verwendest in einer Android-App. Dieser Leitfaden konzentriert sich auf die Verbindung zwischen Zustand und zusammensetzbaren Funktionen und den APIs, die Jetpack Compose bietet, um mit mehr Status zu arbeiten. leicht gemacht.
Status und Zusammensetzung
Die Erstellungsfunktion ist deklarativ und kann daher nur durch Aufrufen der Methode
mit neuen Argumenten zusammensetzbar. Diese Argumente sind Darstellungen der
UI-Status Jedes Mal, wenn ein Status aktualisiert wird, findet eine Neuzusammensetzung statt. Als
führen, werden Dinge wie TextField
nicht automatisch aktualisiert, wie in
und imperative XML-basierte
Ansichten verwendet werden. Einer zusammensetzbaren Funktion muss explizit der neue Status mitgeteilt werden
damit sie entsprechend aktualisiert wird.
@Composable private fun HelloContent() { Column(modifier = Modifier.padding(16.dp)) { Text( text = "Hello!", modifier = Modifier.padding(bottom = 8.dp), style = MaterialTheme.typography.bodyMedium ) OutlinedTextField( value = "", onValueChange = { }, label = { Text("Name") } ) } }
Wenn Sie diesen Befehl ausführen und versuchen, Text einzugeben, werden Sie feststellen, dass nichts passiert. Das sind
da TextField
nicht automatisch aktualisiert wird. Es wird aktualisiert, wenn sein value
Änderungen der Parameter. Das liegt daran, wie Komposition und Neuzusammensetzung
Schreiben.
Weitere Informationen zur anfänglichen Zusammensetzung und Neuzusammensetzung findest du unter In „Schreibe“ denken:
Status in zusammensetzbaren Funktionen
Zusammensetzbare Funktionen können den
remember
API zum Speichern eines Objekts im Arbeitsspeicher. Ein von remember
berechneter Wert ist
in der Komposition gespeichert,
und der gespeicherte Wert wird bei der Neuzusammensetzung zurückgegeben.
Mit remember
können sowohl änderbare als auch unveränderliche Objekte gespeichert werden.
mutableStateOf
eine beobachtbare
MutableState<T>
,
Dabei handelt es sich um einen
beobachtbaren Typ, der in die Compose-Laufzeit integriert ist.
interface MutableState<T> : State<T> {
override var value: T
}
Bei Änderungen an value
wird die Neuzusammensetzung beliebiger zusammensetzbarer Funktionen geplant
mit folgendem Text: value
.
Es gibt drei Möglichkeiten, ein MutableState
-Objekt in einer zusammensetzbaren Funktion zu deklarieren:
val mutableState = remember { mutableStateOf(default) }
var value by remember { mutableStateOf(default) }
val (value, setValue) = remember { mutableStateOf(default) }
Diese Deklarationen sind äquivalent und werden als Syntax Zucker für unterschiedliche Verwendungen von Bundesstaaten. Sie sollten diejenige auswählen, mit der die in der zusammensetzbaren Funktion, die Sie schreiben, ist der lesefreundlichste Code.
Die Delegatsyntax by
erfordert die folgenden Importe:
import androidx.compose.runtime.getValue
import androidx.compose.runtime.setValue
Sie können den gespeicherten Wert als Parameter für andere zusammensetzbare Funktionen oder sogar
in Anweisungen ändern,
welche zusammensetzbaren Funktionen angezeigt werden. Wenn beispielsweise
Soll die Begrüßung nicht angezeigt werden, wenn der Name leer ist, verwenden Sie den Status in einem
if
-Anweisung:
@Composable fun HelloContent() { Column(modifier = Modifier.padding(16.dp)) { var name by remember { mutableStateOf("") } if (name.isNotEmpty()) { Text( text = "Hello, $name!", modifier = Modifier.padding(bottom = 8.dp), style = MaterialTheme.typography.bodyMedium ) } OutlinedTextField( value = name, onValueChange = { name = it }, label = { Text("Name") } ) } }
Mit remember
können Sie den Zustand bei Neuzusammensetzungen beibehalten, aber das ist nicht der Fall.
werden bei allen Konfigurationsänderungen beibehalten. Dazu müssen Sie
rememberSaveable
rememberSaveable
speichert automatisch alle Werte, die
in einem Bundle
gespeichert. Für andere Werte können Sie ein benutzerdefiniertes Saver-Objekt übergeben.
Andere unterstützte Statustypen
Für das Schreiben müssen Sie nicht MutableState<T>
verwenden, um einen Hold-Zustand zu verwenden. sie
andere beobachtbare Typen unterstützt. Bevor Sie einen anderen
beobachtbaren Typ lesen,
Compose-Datei einfügen, müssen Sie es in eine State<T>
konvertieren, damit zusammensetzbare Funktionen
automatisch neu zusammensetzen,
wenn sich der Zustand ändert.
Compose enthält Funktionen zum Erstellen von State<T>
aus gängigen beobachtbaren Elementen
die in Android-Apps verwendet werden. Bevor Sie diese Integrationen verwenden, fügen Sie den
geeignete Artefakte wie unten beschrieben:
Flow
:collectAsStateWithLifecycle()
collectAsStateWithLifecycle()
erfasst Werte aus einerFlow
an den Lebenszyklus angepasst, damit Ihre App die App-Ressourcen zu schonen. Er steht für den letzten ausgegebenen Wert des „Schreiben“State
. Verwenden Sie diese API als empfohlene Methode zum Erfassen von Datenflüssen auf Android-Apps.Die folgende Abhängigkeit ist in der Datei
build.gradle
erforderlich. Sie sollte 2.6.0-beta01 oder höher sein):
Kotlin
dependencies {
...
implementation("androidx.lifecycle:lifecycle-runtime-compose:2.6.2")
}
Cool
dependencies {
...
implementation "androidx.lifecycle:lifecycle-runtime-compose:2.6.2"
}
-
collectAsState
ähneltcollectAsStateWithLifecycle
, weil ebenfalls erfasst Werte aus einerFlow
und wandelt sie in „Schreiben“State
um.Verwenden Sie
collectAsState
für plattformunabhängigen Code anstelle voncollectAsStateWithLifecycle
, das nur für Android verfügbar ist.Für
collectAsState
sind keine zusätzlichen Abhängigkeiten erforderlich, da dies verfügbar incompose-runtime
. -
observeAsState()
beginnt mit der Beobachtung diesesLiveData
und stellt seine Werte dar überState
.Die folgende Abhängigkeit ist in der Datei
build.gradle
erforderlich:
Kotlin
dependencies {
...
implementation("androidx.compose.runtime:runtime-livedata:1.6.8")
}
Cool
dependencies {
...
implementation "androidx.compose.runtime:runtime-livedata:1.6.8"
}
-
subscribeAsState()
sind Erweiterungsfunktionen, die die reaktive RxJava2-Funktion transformieren. Streams (z.B.Single
,Observable
,Completable
) in „Schreiben“State
.Die folgende Abhängigkeit ist in der Datei
build.gradle
erforderlich:
Kotlin
dependencies {
...
implementation("androidx.compose.runtime:runtime-rxjava2:1.6.8")
}
Cool
dependencies {
...
implementation "androidx.compose.runtime:runtime-rxjava2:1.6.8"
}
-
subscribeAsState()
sind Erweiterungsfunktionen, die die reaktive RxJava3-Funktion transformieren. Streams (z.B.Single
,Observable
,Completable
) in „Schreiben“State
.Die folgende Abhängigkeit ist in der Datei
build.gradle
erforderlich:
Kotlin
dependencies {
...
implementation("androidx.compose.runtime:runtime-rxjava3:1.6.8")
}
Cool
dependencies {
...
implementation "androidx.compose.runtime:runtime-rxjava3:1.6.8"
}
Zustandsorientiert oder zustandslos
Eine zusammensetzbare Funktion, die remember
zum Speichern eines Objekts verwendet, erstellt einen internen Status.
damit die zusammensetzbare Funktion zustandsorientiert wird. HelloContent
ist ein Beispiel für eine zustandsorientierte
zusammensetzbar, da sie den name
-Status intern enthält und ändert. Dies kann
in Situationen nützlich sein, in denen der Aufrufer den Status nicht kontrollieren muss
ohne den Status selbst verwalten zu müssen. Zusammensetzbare Funktionen mit
sind in der Regel weniger
wiederverwendbar und schwerer zu testen.
Eine zustandslose zusammensetzbare Funktion ist eine zusammensetzbare Funktion, die keinen Zustand enthält. Eine einfache Zustandslosigkeit erreichen, ist die Verwendung von state Winde.
Bei der Entwicklung wiederverwendbarer zusammensetzbarer Funktionen sollten Sie häufig sowohl eine zustandsorientierte und eine zustandslose Version derselben zusammensetzbaren Funktion. Die zustandsorientierte Version ist praktisch für Aufrufer, für die der Status nicht relevant ist, und für zustandslose Version ist für Aufrufer erforderlich, die den Status steuern oder hochziehen müssen.
Staatliche Winden
Das Hochheben von Status in Compose ist ein Muster, das sich an den Aufrufer einer zusammensetzbaren Funktion bewegt um eine zusammensetzbare zustandslose Lösung zu erstellen. Das allgemeine Muster zum Einheben Jetpack Compose ersetzt die Statusvariable durch zwei Parameter:
value: T
: der aktuell anzuzeigende WertonValueChange: (T) -> Unit
: Ein Ereignis, das eine Änderung des Werts anfordert Dabei istT
der vorgeschlagene neue Wert
Sie sind jedoch nicht auf onValueChange
beschränkt. Wenn spezifischere Ereignisse
sollten Sie sie mithilfe von Lambdas definieren.
Ein Zustand, der auf diese Weise gezogen wird, hat einige wichtige Eigenschaften:
- Single Source of Truth:Wenn wir den Zustand verschieben, anstatt ihn zu duplizieren, wird er dass es nur eine einzige Informationsquelle gibt. So lassen sich Fehler vermeiden.
- Encapsulated (Verkapselt): Der Status kann nur von zustandsorientierten zusammensetzbaren Funktionen geändert werden. Es ist komplett intern arbeiten.
- Gemeinsam nutzbar: Der Hub-Zustand kann mit mehreren zusammensetzbaren Funktionen geteilt werden. Wenn Sie
wollte
name
in einer anderen zusammensetzbaren Funktion lesen. Mit Winden können Sie tun Sie das. - Interceptable (Interceptable):Aufrufer der zustandslosen zusammensetzbaren Funktionen können entscheiden, Ereignisse zu ignorieren oder zu ändern, bevor der Status geändert wird.
- Entkoppelt:Der Status für die zustandslosen zusammensetzbaren Funktionen kann gespeichert werden.
überall. Beispielsweise ist es jetzt möglich,
name
in einenViewModel
zu verschieben.
Im Beispielfall extrahieren Sie name
und onValueChange
aus
HelloContent
und verschieben Sie sie in der Baumstruktur in eine HelloScreen
zusammensetzbare Funktion,
ruft HelloContent
auf.
@Composable fun HelloScreen() { var name by rememberSaveable { mutableStateOf("") } HelloContent(name = name, onNameChange = { name = it }) } @Composable fun HelloContent(name: String, onNameChange: (String) -> Unit) { Column(modifier = Modifier.padding(16.dp)) { Text( text = "Hello, $name", modifier = Modifier.padding(bottom = 8.dp), style = MaterialTheme.typography.bodyMedium ) OutlinedTextField(value = name, onValueChange = onNameChange, label = { Text("Name") }) } }
Durch Heben des Zustands aus HelloContent
ist es einfacher,
zusammensetzbar sind,
in verschiedenen Situationen wiederverwenden und testen. HelloContent
ist
von der Speicherung
seines Zustands entkoppelt ist. Eine Entkopplung bedeutet, dass Sie,
wenn Sie Änderungen oder
HelloScreen
ersetzen, müssen Sie die Einstellungen für HelloContent
nicht ändern
implementiert.
Das Muster, bei dem der Zustand abfällt und die Ereignisse ansteigen,
Unidirektionalen Datenfluss an. In diesem Fall sinkt der Status von HelloScreen
.
auf HelloContent
und die Ereignisse steigen von HelloContent
bis HelloScreen
an. Von
unidirektionalen Datenfluss folgen, können Sie zusammensetzbare Funktionen entkoppeln, die
in der Benutzeroberfläche für die Teile
Ihrer App, in denen der Status gespeichert und geändert wird.
Weitere Informationen finden Sie auf der Seite Windenstatus.
Status in Compose wird wiederhergestellt
Die rememberSaveable
API verhält sich ähnlich wie remember
, weil sie
Beibehaltung des Zustands bei Neuzusammensetzungen und auch bei Aktivitäten oder Prozessen
Wiederherstellung mithilfe des Mechanismus für den gespeicherten Instanzstatus. Das ist zum Beispiel der Fall,
wenn der Bildschirm gedreht wird.
Möglichkeiten zum Speichern des Status
Alle Datentypen, die dem Bundle
hinzugefügt werden, werden automatisch gespeichert. Wenn Sie
etwas speichern möchten, das Bundle
nicht hinzugefügt werden kann, gibt es mehrere
Optionen.
Paket
Die einfachste Lösung besteht darin,
@Parcelize
an das Objekt an. Das Objekt wird geparst und kann gebündelt werden. Für
Beispiel: Dieser Code erstellt einen parierbaren Datentyp City
und speichert ihn im
Bundesstaat.
@Parcelize data class City(val name: String, val country: String) : Parcelable @Composable fun CityScreen() { var selectedCity = rememberSaveable { mutableStateOf(City("Madrid", "Spain")) } }
MapSaver
Wenn @Parcelize
aus irgendeinem Grund nicht geeignet ist, kannst du mapSaver
verwenden, um
definieren Sie Ihre eigene Regel zum Konvertieren eines Objekts in eine Gruppe von Werten,
System in Bundle
speichern kann.
data class City(val name: String, val country: String) val CitySaver = run { val nameKey = "Name" val countryKey = "Country" mapSaver( save = { mapOf(nameKey to it.name, countryKey to it.country) }, restore = { City(it[nameKey] as String, it[countryKey] as String) } ) } @Composable fun CityScreen() { var selectedCity = rememberSaveable(stateSaver = CitySaver) { mutableStateOf(City("Madrid", "Spain")) } }
Listenspeicher
Um zu vermeiden, dass die Schlüssel für die Karte definiert werden müssen, können Sie auch listSaver
verwenden.
und verwenden ihre Indizes als Schlüssel:
data class City(val name: String, val country: String) val CitySaver = listSaver<City, Any>( save = { listOf(it.name, it.country) }, restore = { City(it[0] as String, it[1] as String) } ) @Composable fun CityScreen() { var selectedCity = rememberSaveable(stateSaver = CitySaver) { mutableStateOf(City("Madrid", "Spain")) } }
Staatsinhaber in Compose
Einfache Winden können in den zusammensetzbaren Funktionen selbst verwaltet werden. Wenn jedoch die Menge des Zustands, der Anstiege im Blick behalten soll, oder die Logik, in zusammensetzbaren Funktionen auftreten, empfiehlt es sich, die Daten Logik und Verantwortlichkeiten gegenüber anderen Klassen: Inhabern des Bundesstaats.
Weitere Informationen finden Sie in der Dokumentation zu State Hoisting in Compose oder allgemein in der Weitere Informationen finden Sie auf der Seite State holders and UI State im Architekturleitfaden.
„Berechnungen merken“ noch einmal auslösen, wenn sich Tasten ändern
Die remember
API wird häufig zusammen mit MutableState
verwendet:
var name by remember { mutableStateOf("") }
Hier behält der Wert MutableState
mit der Funktion remember
bei
und Neuzusammensetzungen.
Im Allgemeinen verwendet remember
einen Lambda-Parameter calculation
. Wenn remember
wird die Lambda-Funktion calculation
aufgerufen, und das Ergebnis wird gespeichert. Währenddessen
Zusammensetzung gibt remember
den zuletzt gespeicherten Wert zurück.
Neben dem Caching-Status können Sie mit remember
auch beliebige Objekte oder
Ergebnis eines Vorgangs in der Komposition, deren Initialisierung oder
zu berechnen. Vielleicht möchten Sie diese Berechnung nicht bei jeder Neuzusammensetzung wiederholen.
Ein Beispiel ist die Erstellung dieses ShaderBrush
-Objekts, das eine teure
Vorgang:
val brush = remember { ShaderBrush( BitmapShader( ImageBitmap.imageResource(res, avatarRes).asAndroidBitmap(), Shader.TileMode.REPEAT, Shader.TileMode.REPEAT ) ) }
remember
speichert den Wert, bis er die Komposition verlässt. Es gibt jedoch eine
den im Cache gespeicherten Wert zu entwerten. Die remember
API verwendet auch einen key
- oder
keys
-Parameter. Wenn sich eine dieser Tasten ändert, wird das nächste Mal, wenn die Funktion
Zusammensetzung, remember
entwertet den Cache und führt die Berechnung aus
Lambda-Blockade wieder aktivieren. Mit diesem Mechanismus können Sie die Lebensdauer eines
-Objekt in der Komposition. Die Berechnung bleibt gültig, bis die Eingaben
bis der gespeicherte Wert die Komposition verlässt.
Die folgenden Beispiele zeigen, wie dieser Mechanismus funktioniert.
In diesem Snippet wird ein ShaderBrush
erstellt und als Hintergrund verwendet
Farbe einer Box
zusammensetzbaren Funktion. remember
speichert die Instanz ShaderBrush
da die Neuerstellung teuer ist. remember
Take
avatarRes
als key1
-Parameter. Dies ist das ausgewählte Hintergrundbild. Wenn
avatarRes
ändert, wird der Pinsel mit dem neuen Bild neu zusammengesetzt und auf
Box
. Dies kann passieren, wenn der Nutzer ein anderes Bild als
in einer Auswahl aus.
@Composable private fun BackgroundBanner( @DrawableRes avatarRes: Int, modifier: Modifier = Modifier, res: Resources = LocalContext.current.resources ) { val brush = remember(key1 = avatarRes) { ShaderBrush( BitmapShader( ImageBitmap.imageResource(res, avatarRes).asAndroidBitmap(), Shader.TileMode.REPEAT, Shader.TileMode.REPEAT ) ) } Box( modifier = modifier.background(brush) ) { /* ... */ } }
Im nächsten Snippet wird der Zustand in eine plain State Holder Class hochgezogen.
MyAppState
Sie stellt eine rememberMyAppState
-Funktion zur Verfügung, um ein
Instanz der Klasse mit remember
. Die Bereitstellung solcher Funktionen zum Erstellen eines
-Instanz, die Neuzusammensetzungen überlebt, ist ein gängiges Muster in Compose. Die
rememberMyAppState
-Funktion empfängt windowSizeClass
, die als
key
-Parameter für remember
Wenn sich dieser Parameter ändert, muss die App
erstellen Sie die Halteklasse des einfachen Zustands mit dem neuesten Wert. Das kann in folgenden Fällen passieren:
z. B. wenn der Nutzer das Gerät dreht.
@Composable private fun rememberMyAppState( windowSizeClass: WindowSizeClass ): MyAppState { return remember(windowSizeClass) { MyAppState(windowSizeClass) } } @Stable class MyAppState( private val windowSizeClass: WindowSizeClass ) { /* ... */ }
Compose verwendet die Klasse equals-Implementierung, um zu entscheiden, ob ein Schlüssel geändert und ungültig gemacht werden.
Status mit Schlüsseln über die Neuzusammensetzung hinaus speichern
Die rememberSaveable
API ist ein Wrapper um remember
, der speichern kann,
in einem Bundle
. Mit dieser API kann der Status nicht nur
Neuzusammensetzung, aber auch Erholung und vom System ausgelöste Todesfälle.
rememberSaveable
empfängt input
-Parameter für denselben Zweck, der
remember
erhält keys
. Der Cache wird entwertet, wenn eine der Eingaben
ändern. Bei der nächsten Neuzusammensetzung der Funktion wird rememberSaveable
noch einmal ausgeführt
der Lambda-Blockade berechnet.
Im folgenden Beispiel speichert rememberSaveable
userTypedQuery
bis
typedQuery
-Änderungen:
var userTypedQuery by rememberSaveable(typedQuery, stateSaver = TextFieldValue.Saver) { mutableStateOf( TextFieldValue(text = typedQuery, selection = TextRange(typedQuery.length)) ) }
Weitere Informationen
Weitere Informationen zu Status und Jetpack Compose finden Sie hier zusätzliche Ressourcen.
Produktproben
Codelabs
Videos
Blogs
Empfehlungen für dich
- Hinweis: Der Linktext wird angezeigt, wenn JavaScript deaktiviert ist.
- Benutzeroberfläche für das Schreiben erstellen
- UI-Status in „Compose“ speichern
- Nebeneffekte in der Funktion „Schreiben“