Im UI-Ebenen-Leitfaden wird der unidirektionale Datenfluss (UDF) zur Unterstützung Erstellen und Verwalten des UI-Status für die UI-Ebene
<ph type="x-smartling-placeholder">Außerdem werden die Vorteile der Delegation der UDF-Verwaltung an eine spezielle Klasse hervorgehoben.
als Staatsinhaber genannt. Sie können einen Inhaber eines Bundesstaates entweder über eine
ViewModel
oder eine einfache Klasse. In diesem Dokument wird der Zustand genauer beschrieben.
die Inhaber und ihre Rolle auf der UI-Ebene.
Am Ende dieses Dokuments sollten Sie wissen, wie Sie Anwendungsstatus auf der UI-Ebene. also die Produktionspipeline für den UI-Status. Ich sollte Folgendes verstehen und wissen können:
- Informieren Sie sich über die Arten von UI-Status, die auf der UI-Ebene vorhanden sind.
- Informieren Sie sich über die Arten von Logik, die auf diese UI-Zustände auf der UI-Ebene angewendet werden.
- Sie müssen wissen, wie Sie die geeignete Implementierung eines Bundesstaatsinhabers, z. B. eines
ViewModel
oder eine einfache Klasse.
Elemente der Produktionspipeline für den UI-Status
Der UI-Status und die Logik, die ihn erzeugt, definieren die UI-Ebene.
UI-Status
Der UI-Status ist die Eigenschaft, die die UI beschreibt. Es gibt zwei Arten von UI-Elementen. Bundesland:
- Der Bildschirm-UI-Status gibt an, was auf dem Bildschirm angezeigt werden muss. Beispiel:
NewsUiState
-Kurs kann die Nachrichtenartikel und andere benötigte Informationen enthalten. um die UI zu rendern. Dieser Zustand ist normalerweise mit anderen Schichten des da sie App-Daten enthält. - Der UI-Elementstatus bezieht sich auf Eigenschaften, die UI-Elementen inhärent sind und die
wie sie gerendert werden. Ein UI-Element kann ein- oder ausgeblendet sein und
eine bestimmte Schriftart,
Schriftgröße oder -farbe haben. In Android Views kann die Ansicht
verwaltet diesen Zustand selbst, da er inhärent zustandsorientiert ist und Methoden offenlegt,
ändern oder abfragen können. Ein Beispiel hierfür sind
get
undset
-Methoden der KlasseTextView
für den Text. Im Jetpack Compose-Objekt erstellen, liegt der Status außerhalb der zusammensetzbaren Funktion und Sie können sie sogar winden. aus der unmittelbaren Nähe der zusammensetzbaren Funktion in die aufrufende für eine Funktion oder einen Staatsinhaber sein. Ein Beispiel hierfür istScaffoldState
für denScaffold
zusammensetzbar.
Logik
Der UI-Status ist keine statische Eigenschaft, da Anwendungsdaten und Nutzerereignisse dazu führen, dass die Benutzeroberfläche die sich im Laufe der Zeit ändern. Die Logik bestimmt die Einzelheiten der Änderung, z. B. welche Teile des UI-Status sich geändert haben, warum und wann geändert werden sollte.
<ph type="x-smartling-placeholder">Die Logik in einer Anwendung kann entweder Geschäftslogik oder UI-Logik sein:
- Die Geschäftslogik ist die Implementierung von Produktanforderungen für Apps. Daten. Sie können beispielsweise einen Artikel in einer Newsreader-App als Lesezeichen speichern, tippt auf die Schaltfläche. Diese Logik zum Speichern eines Lesezeichens in einer Datei oder Datenbank normalerweise in den Domänen- oder Datenebenen platziert. Der staatliche Inhaber ist in der Regel delegiert diese Logik an diese Layer, indem die von ihnen bereitgestellten Methoden aufgerufen werden.
- UI-Logik bezieht sich darauf, wie der UI-Status auf dem Bildschirm angezeigt wird. Für Beispiel: Der richtige Suchleistenhinweis wird angezeigt, wenn der Nutzer eine Kategorie, das Scrollen zu einem bestimmten Element in einer Liste oder die Navigationslogik wenn Nutzende auf eine Schaltfläche klicken.
Android-Lebenszyklus und die Arten von UI-Status und -Logik
Die UI-Ebene besteht aus zwei Teilen: einem abhängigen und einem unabhängigen Teil der UI. Lebenszyklus. Durch diese Trennung wird festgelegt, welche Datenquellen für die einzelnen Teile und erfordert daher verschiedene Arten von UI-Zustand und -Logik.
- UI-Lebenszyklus unabhängig: Dieser Teil der UI-Ebene befasst sich mit den Daten
zur Erstellung von App-Ebenen (Daten- oder Domainebenen) und wird vom
Logik. Lebenszyklus, Konfigurationsänderungen und Neuerstellung von
Activity
in der UI kann sich darauf auswirken, ob die Produktionspipeline für den UI-Status aktiv ist, hat aber keine Auswirkungen die Gültigkeit der erzeugten Daten. - Vom UI-Lebenszyklus abhängig: Dieser Teil der UI-Ebene befasst sich mit der UI-Logik und direkt von Lebenszyklus- oder Konfigurationsänderungen beeinflusst. Diese Änderungen sich direkt auf die Gültigkeit der darin gelesenen Datenquellen auswirken. Ergebnis, sein Status kann sich nur ändern, wenn sein Lebenszyklus aktiv ist. Beispiele für Dazu gehören Laufzeitberechtigungen und das Abrufen konfigurationsabhängiger Ressourcen z. B. lokalisierte Zeichenfolgen.
Das kann mit der folgenden Tabelle zusammengefasst werden:
Unabhängig vom UI-Lebenszyklus | Vom UI-Lebenszyklus abhängig |
---|---|
Geschäftslogik | UI-Logik |
Status der Benutzeroberfläche des Bildschirms |
Produktionspipeline für den UI-Status
Die Produktionspipeline für den UI-Status bezieht sich auf die Schritte, die zum Erstellen der UI ausgeführt werden. Bundesstaat. Diese Schritte umfassen die Anwendung der definierten Arten von Logik und hängen ganz von den Anforderungen Ihrer Benutzeroberfläche ab. Einige Benutzeroberflächen profitieren sowohl vom UI-Lebenszyklus als auch vom UI-Lebenszyklus der Pipeline entweder oder keinem von beiden entsprechen.
Das heißt, die folgenden Permutationen der UI-Ebenen-Pipeline sind gültig:
Der UI-Status, der von der UI selbst erstellt und verwaltet wird. Eine einfache, wiederverwendbarer Basic-Zähler:
@Composable fun Counter() { // The UI state is managed by the UI itself var count by remember { mutableStateOf(0) } Row { Button(onClick = { ++count }) { Text(text = "Increment") } Button(onClick = { --count }) { Text(text = "Decrement") } } }
UI-Logik → UI. Zum Beispiel das Ein- oder Ausblenden einer Schaltfläche, mit der Nutzende an den Anfang einer Liste springen.
@Composable fun ContactsList(contacts: List<Contact>) { val listState = rememberLazyListState() val isAtTopOfList by remember { derivedStateOf { listState.firstVisibleItemIndex < 3 } } // Create the LazyColumn with the lazyListState ... // Show or hide the button (UI logic) based on the list scroll position AnimatedVisibility(visible = !isAtTopOfList) { ScrollToTopButton() } }
Geschäftslogik → Benutzeroberfläche. Ein UI-Element, das das Foto des aktuellen Nutzers auf der Bildschirm.
@Composable fun UserProfileScreen(viewModel: UserProfileViewModel = hiltViewModel()) { // Read screen UI state from the business logic state holder val uiState by viewModel.uiState.collectAsStateWithLifecycle() // Call on the UserAvatar Composable to display the photo UserAvatar(picture = uiState.profilePicture) }
Geschäftslogik → UI-Logik → UI. Ein UI-Element, das gescrollt wird, um die Informationen auf dem Bildschirm für einen jeweiligen UI-Zustand richtig angezeigt.
@Composable fun ContactsList(viewModel: ContactsViewModel = hiltViewModel()) { // Read screen UI state from the business logic state holder val uiState by viewModel.uiState.collectAsStateWithLifecycle() val contacts = uiState.contacts val deepLinkedContact = uiState.deepLinkedContact val listState = rememberLazyListState() // Create the LazyColumn with the lazyListState ... // Perform UI logic that depends on information from business logic if (deepLinkedContact != null && contacts.isNotEmpty()) { LaunchedEffect(listState, deepLinkedContact, contacts) { val deepLinkedContactIndex = contacts.indexOf(deepLinkedContact) if (deepLinkedContactIndex >= 0) { // Scroll to deep linked item listState.animateScrollToItem(deepLinkedContactIndex) } } } }
Wenn beide Arten von Logik auf die Erstellung des UI-Zustands angewendet werden Pipeline muss die Geschäftslogik immer vor der UI-Logik angewendet werden. Wird angewendet Nach der UI-Logik würde die Geschäftslogik implizieren, dass die Geschäftslogik von der Benutzeroberfläche abhängt. Logik. In den folgenden Abschnitten wird ausführlich erläutert, verschiedene Logiktypen und ihre Zustandsinhaber.
<ph type="x-smartling-placeholder">Inhaber von Bundesstaaten und ihre Verantwortlichkeiten
Die Verantwortung eines Zustandsinhabers besteht darin, den Status zu speichern, damit die App ihn lesen kann. Wenn Logik erforderlich ist, fungiert sie als Vermittler und bietet Zugriff zu den Datenquellen, die die erforderliche Logik hosten. Auf diese Weise die Logik an die entsprechende Datenquelle delegiert.
Dies hat folgende Vorteile:
- Einfache Benutzeroberflächen: Die Benutzeroberfläche bindet nur ihren Status.
- Verwaltbarkeit: Die im Statusinhaber definierte Logik kann iteriert werden. ohne die Benutzeroberfläche selbst zu ändern.
- Testbarkeit: Die Benutzeroberfläche und ihre Statusproduktionslogik können getestet werden. unabhängig voneinander unterscheiden.
- Lesbarkeit: Die Leser des Codes können die Unterschiede zwischen der Benutzeroberfläche deutlich erkennen. Präsentationscode und UI-Status-Produktionscode.
Unabhängig von Größe oder Umfang hat jedes UI-Element eine 1:1-Beziehung für den jeweiligen Staatsinhaber. Darüber hinaus müssen Staatsinhaber in der Lage sein, alle Nutzeraktionen zu akzeptieren und zu verarbeiten, die zu einer Änderung des UI-Status führen könnten, die damit einhergehende Statusänderung erzeugen muss.
Arten von Staatsinhabern
Ähnlich wie bei UI-Status und -Logik gibt es zwei Arten von Statusinhabern in der UI-Ebene definiert durch ihre Beziehung zum UI-Lebenszyklus:
- Der Inhaber der Geschäftslogik.
- Der Inhaber des UI-Logikstatus.
In den folgenden Abschnitten geht es um die verschiedenen angefangen mit dem Inhaber der Geschäftslogik.
Geschäftslogik und ihr Statusinhaber
Inhaber von Geschäftslogikstatus verarbeiten Nutzerereignisse und transformieren Daten aus den Daten oder der Domain Bildschirm-UI-Status hinzugefügt. Um eine optimale Nutzererfahrung zu bieten, unter Berücksichtigung des Android-Lebenszyklus und der Änderungen an der App-Konfiguration, die Geschäftslogik verwenden, sollten folgende Attribute haben:
Attribut | Details |
---|---|
Erzeugt UI-Status | Inhaber der Geschäftslogik sind für die Erstellung des UI-Status für ihre UIs verantwortlich. Dieser UI-Status ist häufig das Ergebnis der Verarbeitung von Nutzerereignissen und dem Lesen von Daten aus der Domain und den Datenschichten. |
Erhalten durch Freizeitaktivitäten | Inhaber von Geschäftslogikstatus behalten ihre Status- und Statusverarbeitungspipelines über die Activity -Neuerstellung hinweg bei und bieten so eine nahtlose Nutzererfahrung. In Fällen, in denen der Zustandsinhaber nicht beibehalten werden kann und neu erstellt wird (normalerweise nach dem Prozess Tod), muss der Inhaber seinen letzten Status einfach reproduzieren können, um eine konsistente Nutzererfahrung zu gewährleisten. |
Hat einen langlebigen Zustand | Inhaber von Geschäftslogikstatus werden häufig verwendet, um den Status für Navigationsziele zu verwalten. Daher behalten sie häufig ihren Status über alle Navigationsänderungen hinweg bei, bis sie aus dem Navigationsdiagramm entfernt werden. |
Sie ist für die zugehörige Benutzeroberfläche eindeutig und nicht wiederverwendbar. | Inhaber von Geschäftslogikstatus generieren in der Regel einen Status für eine bestimmte App-Funktion, z. B. eine TaskEditViewModel oder eine TaskListViewModel . Daher gilt sie immer nur für diese App-Funktion. Derselbe Bundesstaat kann diese App-Funktionen für verschiedene Formfaktoren unterstützen. Beispielsweise kann in Smartphone-, TV- und Tablet-Versionen der App derselbe Inhaber der Geschäftslogik verwendet werden. |
Nehmen wir zum Beispiel das Navigationsziel des Autors im Feld "Now in Android“ App:
<ph type="x-smartling-placeholder">Als Inhaber der Geschäftslogik fungiert der
AuthorViewModel
erzeugt in diesem Fall den UI-Status:
@HiltViewModel
class AuthorViewModel @Inject constructor(
savedStateHandle: SavedStateHandle,
private val authorsRepository: AuthorsRepository,
newsRepository: NewsRepository
) : ViewModel() {
val uiState: StateFlow<AuthorScreenUiState> = …
// Business logic
fun followAuthor(followed: Boolean) {
…
}
}
Beachten Sie, dass AuthorViewModel
die zuvor beschriebenen Attribute hat:
Attribut | Details |
---|---|
produziert AuthorScreenUiState |
AuthorViewModel liest Daten aus AuthorsRepository und NewsRepository und verwendet diese Daten, um AuthorScreenUiState zu erstellen. Außerdem wird Geschäftslogik angewendet, wenn der Nutzer Author durch Delegieren an die AuthorsRepository folgen oder nicht mehr folgen möchte. |
Hat Zugriff auf die Datenschicht | Eine Instanz von AuthorsRepository und NewsRepository wird in ihrem Konstruktor an die Instanz übergeben, damit sie die Geschäftslogik für das folgende Ereignis implementieren kann: Author . |
Überlebt Activity Freizeit |
Da er mit einem ViewModel implementiert ist, wird er über eine schnelle Activity -Neuerstellung hinweg beibehalten. Wenn ein Prozess abgebrochen wird, kann das Objekt SavedStateHandle ausgelesen werden, um die Mindestmenge an Informationen bereitzustellen, die zum Wiederherstellen des UI-Status aus der Datenschicht erforderlich sind. |
Besitzt langlebigen Zustand | ViewModel bezieht sich auf das Navigationsdiagramm. Solange das Ziel des Autors nicht aus dem Navigationsdiagramm entfernt wird, bleibt der Status der Benutzeroberfläche im uiState -StateFlow im Arbeitsspeicher. Die Verwendung von StateFlow bietet außerdem den Vorteil, dass die Anwendung der Geschäftslogik, die den Zustand erzeugt, faul ist, da der Zustand nur erzeugt wird, wenn es einen Collector des UI-Status gibt. |
Sie ist einzigartig für die zugehörige Benutzeroberfläche. | Das AuthorViewModel gilt nur für das Navigationsziel des Verfassers und kann nirgendwo sonst wiederverwendet werden. Wenn eine Geschäftslogik vorhanden ist, die über Navigationsziele hinweg wiederverwendet wird, muss diese Geschäftslogik in eine Komponente auf Daten- oder Domainebene gekapselt werden. |
ViewModel als Inhaber der Geschäftslogik
Dank der Vorteile von ViewModels bei der Android-Entwicklung sind sie für der Zugriff auf die Geschäftslogik ermöglicht und die Anwendungsdaten für auf dem Bildschirm anzuzeigen. Zu diesen Vorteilen gehört Folgendes:
- Von ViewModels ausgelöste Vorgänge bleiben über Konfigurationsänderungen erhalten.
- Integration in Navigation:
<ph type="x-smartling-placeholder">
- </ph>
- Navigation speichert ViewModels im Cache, während sich der Bildschirm im Back Stack befindet. Dies ist dass Ihre zuvor geladenen Daten sofort verfügbar sind, wenn Sie zu Ihrem Ziel zurückkehren. Das ist schwieriger, der dem Lebenszyklus des zusammensetzbaren Bildschirms folgt.
- ViewModel wird auch gelöscht, wenn das Ziel von der Rückseite getrennt wird. Dadurch wird sichergestellt, dass der Zustand automatisch bereinigt wird. Dies ist als auf die zusammensetzbare Entsorgung von Daten, z. B. dass ein neuer Bildschirm aufgerufen wird, weil eine Konfiguration Änderung oder aus anderen Gründen.
- Integration in andere Jetpack-Bibliotheken wie Hilt
UI-Logik und ihr Statusinhaber
Die UI-Logik ist die Logik, die auf Daten angewendet wird, die von der Benutzeroberfläche selbst bereitgestellt werden. Dabei kann es sich um
zu UI-Elementen“ oder auf UI-Datenquellen wie der Permissions API oder
Resources
State Owners, die Benutzeroberflächenlogik verwenden, haben in der Regel
folgenden Properties:
- Erstellt den UI-Status und verwaltet den Status der UI-Elemente
- Überlebt nicht die Wiederherstellung von
Activity
: Staatsinhaber, die in der UI gehostet werden Logik hängt oft von Datenquellen aus der Benutzeroberfläche selbst ab. Beibehalten dieser Informationen bei Konfigurationsänderungen häufiger als nicht zu einem eines Speicherlecks. Wenn die Inhaber der Bundesstaaten Daten über die gesamte Konfiguration hinweg beibehalten müssen ändert sich an eine andere Komponente delegieren müssen, die besser zum Überleben vonActivity
geeignet ist Freizeitaktivitäten. In Jetpack Compose zum Beispiel „Zusammensetzbare UI-Elementzustände“ Funktionen, die mitremembered
-Funktionen erstellt wurden, werden oft anrememberSaveable
delegiert, Beibehaltung des Zustands durch die Neuerstellung vonActivity
. Beispiele für solche Funktionen umfassenrememberScaffoldState()
undrememberLazyListState()
. - Enthält Verweise auf UI-bezogene Datenquellen: Datenquellen wie Lebenszyklus-APIs und -Ressourcen können sicher als UI-Logik referenziert und gelesen werden. hat den gleichen Lebenszyklus wie die UI.
- Ist in mehreren UIs wiederverwendbar: Verschiedene Instanzen derselben UI-Logik kann in verschiedenen Teilen der App wiederverwendet werden. Beispiel: Ein Bundesland Der Inhaber zum Verwalten von Nutzereingabeereignissen für eine Chipgruppe kann bei einer Suche verwendet werden für Infofelder für Filter und für die für Empfänger einer E-Mail.
Der UI-Logikstatusinhaber wird in der Regel mit einer einfachen Klasse implementiert. Dies ist da die UI selbst für die Erstellung des UI-Logikstatus verantwortlich ist. Holder und der UI-Logikstatusinhaber haben denselben Lebenszyklus wie die UI selbst. In Jetpack Compose ist der Staatsinhaber beispielsweise Teil der Komposition und Lebenszyklus der Komposition.
Dies lässt sich anhand des folgenden Beispiels in der Now in Android-Beispiel:
<ph type="x-smartling-placeholder">Das Beispiel „Now in Android“ zeigt entweder eine untere App-Leiste oder eine Navigationsleiste für je nach Bildschirmgröße des Geräts anpassen. Für kleinere Bildschirme App-Leiste am unteren Rand und größere Bildschirme die Navigationsleiste.
Da die Logik zur Auswahl des geeigneten UI-Elements für die Navigation in der
Die zusammensetzbare Funktion NiaApp
hängt nicht von der Geschäftslogik ab und kann verwaltet werden
durch einen einfachen Klassenstatusinhaber namens NiaAppState
:
@Stable
class NiaAppState(
val navController: NavHostController,
val windowSizeClass: WindowSizeClass
) {
// UI logic
val shouldShowBottomBar: Boolean
get() = windowSizeClass.widthSizeClass == WindowWidthSizeClass.Compact ||
windowSizeClass.heightSizeClass == WindowHeightSizeClass.Compact
// UI logic
val shouldShowNavRail: Boolean
get() = !shouldShowBottomBar
// UI State
val currentDestination: NavDestination?
@Composable get() = navController
.currentBackStackEntryAsState().value?.destination
// UI logic
fun navigate(destination: NiaNavigationDestination, route: String? = null) { /* ... */ }
/* ... */
}
Im obigen Beispiel lauten die folgenden Details zur NiaAppState
:
beachten:
- Überlebt
Activity
-Regeneration nicht:NiaAppState
istremembered
in die Komposition mithilfe einer zusammensetzbaren FunktionrememberNiaAppState
und folgen Sie dabei den Namenskonventionen für "Compose". Nachdem derActivity
neu erstellt wurde, wird der die vorherige Instanz verloren geht und eine neue Instanz mit all ihren übergeben werden, die der neuen Konfiguration des hatActivity
neu erstellt. Diese Abhängigkeiten können neu sein oder aus dem vorherigen Konfiguration.rememberNavController()
wird beispielsweise verwendet inNiaAppState
und delegiert sie anrememberSaveable
, den Zustand beiActivity
Neuerstellung beibehalten. - Enthält Verweise auf UI-bezogene Datenquellen: Verweise auf die
navigationController
,Resources
und andere ähnliche Lebenszyklustypen können sicher inNiaAppState
aufbewahrt werden, da sie denselben Lebenszyklusbereich haben.
Wählen Sie zwischen einem ViewModel und einer einfachen Klasse für einen Staatsinhaber aus.
Wählen Sie in den obigen Abschnitten zwischen einem ViewModel
- und einem einfachen Klassenstatus
auf die Logik angewendet, die auf den UI-Status
und die Datenquellen angewendet wird,
auf die die Logik arbeitet.
Das Diagramm unten zeigt zusammenfassend die Position von Statusinhabern in der Benutzeroberfläche. Status der Produktionspipeline:
<ph type="x-smartling-placeholder">Letztendlich sollten Sie den UI-Status mit den State Owners erstellen, die am nächsten
wo sie konsumiert werden. Weniger formell: Sie sollten so wenig
unter Aufrechterhaltung der
richtigen Eigentümerschaft möglich. Wenn Sie Zugriff auf geschäftliche
und der UI-Status beibehalten werden muss,
solange ein Bildschirm aufgerufen wird.
Auch in der Kategorie "Activity
" ist ein ViewModel
eine gute Wahl für
die Implementierung des Statusinhabers
in der Geschäftslogik. Für kurzlebigen UI-Status und
UI-Logik: Eine einfache Klasse, deren Lebenszyklus ausschließlich von der Benutzeroberfläche abhängt, sollte
ausreichend ist.
Staatsinhaber können mehrere
Staatsinhaber können sich auf andere Staatsinhaber verlassen, solange die Abhängigkeiten gleicher oder kürzerer Lebensdauer. Beispiele:
- Ein Inhaber eines UI-Logikstatus kann von einem anderen Inhaber der Benutzeroberflächenlogik abhängig sein.
- kann ein Statusinhaber auf Bildschirmebene von einem UI-Logikstatusinhaber abhängig sein.
Das folgende Code-Snippet zeigt, wie bei Compose's DrawerState
einen anderen internen Statusinhaber, SwipeableState
, und wie die UI-Logik
Inhaber eines Bundesstaats könnte von DrawerState
abhängig sein:
@Stable
class DrawerState(/* ... */) {
internal val swipeableState = SwipeableState(/* ... */)
// ...
}
@Stable
class MyAppState(
private val drawerState: DrawerState,
private val navController: NavHostController
) { /* ... */ }
@Composable
fun rememberMyAppState(
drawerState: DrawerState = rememberDrawerState(DrawerValue.Closed),
navController: NavHostController = rememberNavController()
): MyAppState = remember(drawerState, navController) {
MyAppState(drawerState, navController)
}
Ein Beispiel für eine Abhängigkeit, die einen Zustandsinhaber überlebt, wäre eine UI-Logik. Dies hängt von einem State Holder auf Bildschirmebene ab. Das würde die Wiederverwendbarkeit des kurzlebigen Staatsinhabers und bietet ihm Zugriff auf mehr Logik. als sie tatsächlich benötigt.
Wenn der Inhaber mit kürzerer Lebensdauer bestimmte Informationen von einem übergeordneten geben Sie als Parameter nur die notwendigen Informationen weiter, und übergeben die Instanz des Statusinhabers. Nehmen wir als Beispiel das folgende Code-Snippet: Die UI-Logik-Zustandsinhaberklasse erhält nur das, was sie als Parameter benötigt. nicht die gesamte ViewModel-Instanz als Abhängigkeit.
class MyScreenViewModel(/* ... */) {
val uiState: StateFlow<MyScreenUiState> = /* ... */
fun doSomething() { /* ... */ }
fun doAnotherThing() { /* ... */ }
// ...
}
@Stable
class MyScreenState(
// DO NOT pass a ViewModel instance to a plain state holder class
// private val viewModel: MyScreenViewModel,
// Instead, pass only what it needs as a dependency
private val someState: StateFlow<SomeState>,
private val doSomething: () -> Unit,
// Other UI-scoped types
private val scaffoldState: ScaffoldState
) {
/* ... */
}
@Composable
fun rememberMyScreenState(
someState: StateFlow<SomeState>,
doSomething: () -> Unit,
scaffoldState: ScaffoldState = rememberScaffoldState()
): MyScreenState = remember(someState, doSomething, scaffoldState) {
MyScreenState(someState, doSomething, scaffoldState)
}
@Composable
fun MyScreen(
modifier: Modifier = Modifier,
viewModel: MyScreenViewModel = viewModel(),
state: MyScreenState = rememberMyScreenState(
someState = viewModel.uiState.map { it.toSomeState() },
doSomething = viewModel::doSomething
),
// ...
) {
/* ... */
}
Das folgende Diagramm zeigt die Abhängigkeiten zwischen der UI und verschiedenen die Inhaber des vorherigen Code-Snippets sind:
<ph type="x-smartling-placeholder">Produktproben
In den folgenden Google-Beispielen wird die Verwendung von Staatsinhabern in der Region UI-Ebene. Sehen Sie sich diese Tipps in der Praxis an:
Empfehlungen für dich
- Hinweis: Der Linktext wird angezeigt, wenn JavaScript deaktiviert ist.
- UI-Ebene
- UI State-Produktion
- Leitfaden zur Anwendungsarchitektur