In Compose ist die Benutzeroberfläche unveränderlich. Sie kann nicht mehr aktualisiert werden, nachdem sie
gezeichnet. Sie können den Status Ihrer Benutzeroberfläche steuern. Jedes Mal, wenn der Status der
Änderungen an der Benutzeroberfläche hat Compose die Teile der UI-Struktur neu erstellt, die
geändert. Composables können
„State“- und „Exposure“-Ereignissen angezeigt. Ein TextField
akzeptiert z. B. einen Wert und stellt
einen Callback-onValueChange
, der den Callback-Handler anfordert, die
Wert.
var name by remember { mutableStateOf("") } OutlinedTextField( value = name, onValueChange = { name = it }, label = { Text("Name") } )
Zusammensetzbare Funktionen akzeptieren Status- und Veröffentlichungsereignisse, sodass der unidirektionale Datenfluss Muster gut zu Jetpack Compose passt. In diesem Leitfaden wird erläutert, wie Sie das Muster des unidirektionalen Datenflusses in Compose, die Implementierung von Ereignissen und wie ViewModels in Compose verwendet werden.
Unidirektionaler Datenfluss
Ein unidirektionaler Datenfluss (UDF) ist ein Designmuster, bei dem der Zustand nach unten fließt. und Ereignisse fließen in die Höhe. Wenn Sie dem unidirektionalen Datenfluss folgen, können Sie zusammensetzbare Funktionen, die in der Benutzeroberfläche den Status der Teile Ihrer App anzeigen, die und den Status ändern.
Die Aktualisierungsschleife der Benutzeroberfläche für eine Anwendung mit unidirektionalem Datenfluss sieht so aus:
- Ereignis: In einem Teil der Benutzeroberfläche wird ein Ereignis generiert und nach oben übergeben, z. B. Schaltflächenklick, der an die zu verarbeitende ViewModel-Ressource übergeben wird; oder ein Ereignis vom andere Ebenen Ihrer App, z. B. die Angabe, dass die Nutzersitzung abgelaufen.
- Aktualisierungsstatus: Ein Event-Handler kann den Status ändern.
- Anzeigestatus: Der Statusinhaber übergibt den Status und die Benutzeroberfläche wird angezeigt. .
Dieses Muster bei der Verwendung von Jetpack Compose bietet mehrere Vorteile:
- Testbarkeit: Die Entkopplung des Status von der angezeigten UI erleichtert die Überprüfung. um beide isoliert zu testen.
- Zustandskapselung: Da Statuswerte nur an einer Stelle aktualisiert werden können und gibt es nur eine einzige Informationsquelle für den Zustand einer zusammensetzbaren Funktion: kann es aufgrund von inkonsistenten Status zu Fehlern kommen.
- Konsistenz der Benutzeroberfläche: Alle Statusaktualisierungen werden sofort auf der Benutzeroberfläche
die Nutzung beobachtbarer Staatsinhaber wie
StateFlow
oderLiveData
.
Unidirektionaler Datenfluss in Jetpack Compose
Zusammensetzbare Funktionen basieren auf Status und Ereignissen. Beispielsweise ist ein TextField
nur
aktualisiert, wenn der value
-Parameter aktualisiert wird und ein onValueChange
-Objekt
Callback: Ein Ereignis, das die Änderung des Werts in einen neuen Wert anfordert. Verfassen
definiert das State
-Objekt als Werthalter und ändert den Statuswert
eine Neuzusammensetzung auslösen. Sie können den Status in einer
remember { mutableStateOf(value) }
oder
rememberSaveable { mutableStateOf(value)
, je nachdem, wie lange
wenn wir uns den Wert merken.
Der Typ des Werts der zusammensetzbaren Funktion TextField
ist String
.
von einem hartcodierten Wert, aus einem ViewModel oder vom
Parent composable. Sie müssen sie nicht in einem State
-Objekt speichern,
, um den Wert zu aktualisieren, wenn onValueChange
aufgerufen wird.
Zusammensetzbare Parameter definieren
Behalten Sie bei der Definition der Statusparameter einer zusammensetzbaren Funktion Folgendes bei: sollten Sie sich die folgenden Fragen stellen:
- Wie wiederverwendbar oder flexibel ist die zusammensetzbare Funktion?
- Wie wirken sich die Statusparameter auf die Leistung dieser zusammensetzbaren Funktion aus?
Um die Entkopplung und Wiederverwendung zu fördern, sollte jede zusammensetzbare Funktion die geringste Menge an Daten enthalten. von Informationen. Wenn Sie beispielsweise eine zusammensetzbare Funktion für die in der Kopfzeile eines Nachrichtenartikels, ziehen Sie es vor, nur die Informationen zu übergeben, die und nicht der gesamte Artikel angezeigt wird:
@Composable fun Header(title: String, subtitle: String) { // Recomposes when title or subtitle have changed. } @Composable fun Header(news: News) { // Recomposes when a new instance of News is passed in. }
Manchmal wird durch die Verwendung einzelner Parameter auch die Leistung verbessert. Beispiel:
News
enthält mehr Informationen als nur title
und subtitle
, wenn ein
neue Instanz von News
an Header(news)
übergeben wird, wird die zusammensetzbare Funktion
neu zusammensetzen, auch wenn sich title
und subtitle
nicht geändert haben.
Überlegen Sie sich genau, wie viele Parameter Sie übergeben. Eine Funktion mit Zu viele Parameter verringern die Ergonomie der Funktion. Wir empfehlen, sie in einer Klasse zu gruppieren.
Ereignisse in Editor
Jede Eingabe in Ihrer App sollte als Ereignis dargestellt werden: Tippen, Textänderungen,
und sogar Timer und Updates. Da sich diese Ereignisse
den Status Ihrer Benutzeroberfläche ändern,
ViewModel
sollte derjenige sein, der sie verarbeiten und den UI-Status aktualisieren soll.
Die UI-Ebene sollte den Status nie außerhalb eines Event-Handlers ändern, da dies kann zu Inkonsistenzen und Fehlern in Ihrer Anwendung führen.
Bevorzugt die Übergabe unveränderlicher Werte für Zustands- und Event-Handler-Lambdas. Dieses -Ansatz bietet folgende Vorteile:
- Sie verbessern die Wiederverwendbarkeit.
- Achten Sie darauf, dass Ihre Benutzeroberfläche den Wert des Status nicht direkt ändert.
- Sie vermeiden Nebenläufigkeitsprobleme, da Sie sicherstellen, dass der Status nicht von einem anderen Thread geändert.
- Häufig reduzieren Sie die Codekomplexität.
So kann beispielsweise eine zusammensetzbare Funktion, die String
und Lambda als Parameter akzeptiert,
kann aus vielen Kontexten aufgerufen werden
und ist wiederverwendbar. Angenommen, die Top-App
in Ihrer App zeigt immer Text an und verfügt über eine Zurück-Schaltfläche. Sie können eine
allgemeinere MyAppTopAppBar
-Zusammensetzbare Funktion, die den Text und die Rückseite empfängt
Ziehpunkt als Parameter:
@Composable fun MyAppTopAppBar(topAppBarText: String, onBackPressed: () -> Unit) { TopAppBar( title = { Text( text = topAppBarText, textAlign = TextAlign.Center, modifier = Modifier .fillMaxSize() .wrapContentSize(Alignment.Center) ) }, navigationIcon = { IconButton(onClick = onBackPressed) { Icon( Icons.Filled.ArrowBack, contentDescription = localizedString ) } }, // ... ) }
ViewModels, Status und Ereignisse: ein Beispiel
Mit ViewModel
und mutableStateOf
können Sie auch unidirektionale Daten einführen.
in Ihrer App implementieren, wenn einer der folgenden Punkte zutrifft:
- Der Status der UI wird über beobachtbare Statusinhaber wie
StateFlow
oderLiveData
offengelegt. ViewModel
verarbeitet Ereignisse, die von der Benutzeroberfläche oder anderen Ebenen Ihrer App stammen. und aktualisiert den Inhaber des Bundesstaats basierend auf den Ereignissen.
Tippen Sie beispielsweise bei der Implementierung eines Anmeldebildschirms auf die Schaltfläche Anmelden. sollte in der App ein rotierendes Ladesymbol und ein Netzwerkanruf angezeigt werden. Wenn die die Anmeldung erfolgreich war, wechselt die App zu einem anderen Bildschirm. im Fall von Bei einem Fehler zeigt die App eine Snackbar an. So modellieren Sie den Bildschirmstatus: und das Ereignis:
Der Bildschirm hat vier Status:
- Abgemeldet: Der Nutzer hat sich noch nicht angemeldet.
- In Bearbeitung: wenn in der App derzeit versucht wird, den Nutzer über einen Netzwerkaufruf durchführt.
- Fehler: bei der Anmeldung ist ein Fehler aufgetreten.
- Angemeldet: Der Nutzer ist angemeldet.
Sie können diese Zustände als versiegelte Klasse modellieren. ViewModel
stellt den Status als
eine State
, legt den Anfangszustand fest und aktualisiert ihn nach Bedarf. Die
ViewModel
verarbeitet auch das Anmeldeereignis, indem es eine onSignIn()
-Methode verfügbar macht.
class MyViewModel : ViewModel() { private val _uiState = mutableStateOf<UiState>(UiState.SignedOut) val uiState: State<UiState> get() = _uiState // ... }
Zusätzlich zur mutableStateOf
API bietet Compose
Erweiterungen für LiveData
, Flow
und
Observable
, um sich als Listener zu registrieren und den Wert als Status darzustellen.
class MyViewModel : ViewModel() { private val _uiState = MutableLiveData<UiState>(UiState.SignedOut) val uiState: LiveData<UiState> get() = _uiState // ... } @Composable fun MyComposable(viewModel: MyViewModel) { val uiState = viewModel.uiState.observeAsState() // ... }
Weitere Informationen
Weitere Informationen zur Architektur in Jetpack Compose finden Sie in den folgenden Ressourcen:
Produktproben
Empfehlungen für dich
- Hinweis: Der Linktext wird angezeigt, wenn JavaScript deaktiviert ist.
- State und Jetpack Compose
- UI-Status in „Compose“ speichern
- Nutzereingaben verarbeiten