Die Paging-Bibliothek verfolgt den Status von Ladeanfragen für Seiteninhalte und stellt
ihn über die LoadState Klasse zur Verfügung.
Für jedes
LoadType und Datenquelltyp
(entweder PagingSource oder
RemoteMediator) wird ein separates LoadState-Signal bereitgestellt. Das
CombinedLoadStates
-Objekt, das vom Listener bereitgestellt wird, enthält Informationen zum Ladestatus
aus allen diesen Signalen. Anhand dieser detaillierten Informationen können Sie Ihren Nutzern die entsprechenden Ladeindikatoren anzeigen.
Ladestatus
Die Paging-Bibliothek stellt den Ladestatus für die Verwendung in der UI über das LoadState-Objekt zur Verfügung. LoadState -Objekte können je nach aktuellem Ladestatus eine von drei Formen annehmen:
- Wenn kein aktiver Ladevorgang und kein Fehler vorliegt, ist
LoadStateeinLoadState.NotLoadingObjekt. Diese Unterklasse enthält auch dieendOfPaginationReachedProperty, die angibt, ob das Ende der Paginierung erreicht wurde. - Wenn ein aktiver Ladevorgang vorliegt, ist
LoadStateeinLoadState.LoadingObjekt. - Wenn ein Fehler vorliegt, ist
LoadStateeinLoadState.Error-Objekt.
Sie können auf diese Status über die loadState Property Ihres
LazyPagingItems Wrappers zugreifen. Sie können diesen Status auf zwei Arten verwenden: Sie können die Sichtbarkeit des Hauptinhalts verwalten (z. B. mit einem Aktualisierungs-Spinner im Vollbildmodus) oder Ladeelemente direkt in Ihren LazyColumn-Stream einfügen (z. B. einen Fußzeilen-Spinner).
Mit einem Listener auf den Ladestatus zugreifen
Wenn Sie den Ladestatus in Ihrer UI beobachten möchten, verwenden Sie die loadState Property
, die vom LazyPagingItems Wrapper bereitgestellt wird. Dadurch wird ein
CombinedLoadStates-Objekt zurückgegeben, mit dem Sie auf das Ladeverhalten für
Aktualisierungs-, Anfüge- oder Voranfügeereignisse reagieren können.
Im folgenden Beispiel zeigt die UI je nach aktuellem Status des Aktualisierungsladevorgangs (initial) einen Lade-Spinner oder eine Fehlermeldung an:
@Composable fun UserListScreen(viewModel: UserViewModel) { val pagingItems = viewModel.flow.collectAsLazyPagingItems() Box(modifier = Modifier.fillMaxSize()) { // Show the list content LazyColumn { items(pagingItems.itemCount) { index -> UserItem(pagingItems[index]) } } // Handle the loading state when (val state = pagingItems.loadState.refresh) { is LoadState.Loading -> { CircularProgressIndicator(modifier = Modifier.align(Alignment.Center)) } is LoadState.Error -> { ErrorButton( message = state.error.message ?: "Unknown error", onClick = { pagingItems.retry() }, modifier = Modifier.align(Alignment.Center) ) } else -> {} // No separate view needed for success/not loading } } }
Weitere Informationen zu LazyPagingItems finden Sie unter Große Datensätze (Paginierung).
Lade-Kopf- und -Fußzeilen hinzufügen
Wenn Sie am Anfang oder Ende Ihrer Liste Ladeindikatoren als Kopf- oder Fußzeilen anzeigen möchten, fügen Sie innerhalb des Bereichs LazyColumn spezielle Elementblöcke für diese Status hinzu.
Mit dem Objekt CombinedLoadStates können Sie den Voranfügestatus für die Kopfzeile und den Anfügestatus für die
Fußzeile beobachten.
Im folgenden Beispiel wird unten in der Liste eine Fortschrittsanzeige oder eine Schaltfläche zum Wiederholen angezeigt, wenn weitere Daten abgerufen werden:
@Composable fun UserList(viewModel: UserViewModel) { val pagingItems = viewModel.pager.flow.collectAsLazyPagingItems() LazyColumn { // 1. Header (Prepend state) // Useful if you support bidirectional paging or jumping to the middle item { val prependState = pagingItems.loadState.prepend if (prependState is LoadState.Loading) { LoadingItem() } else if (prependState is LoadState.Error) { ErrorItem( message = prependState.error.message ?: "Error", onClick = { pagingItems.retry() } ) } } // 2. Main Data items(pagingItems.itemCount) { index -> UserItem(pagingItems[index]) } // 3. Footer (Append state) // Shows when the user scrolls to the bottom and more data is loading item { val appendState = pagingItems.loadState.append if (appendState is LoadState.Loading) { LoadingItem() } else if (appendState is LoadState.Error) { ErrorItem( message = appendState.error.message ?: "Error", onClick = { pagingItems.retry() } ) } } } } @Composable fun LoadingItem() { Box(modifier = Modifier.fillMaxWidth().padding(16.dp), contentAlignment = Alignment.Center) { CircularProgressIndicator() } } @Composable fun ErrorItem(message: String, onClick: () -> Unit) { Column( modifier = Modifier.fillMaxWidth().padding(16.dp), horizontalAlignment = Alignment.CenterHorizontally ) { Text(text = message, color = Color.Red) Button(onClick = onClick) { Text("Retry") } } }
Auf zusätzliche Informationen zum Ladestatus zugreifen
Wie in den vorherigen Beispielen gezeigt, ist der Aufruf von pagingItems.loadState.refresh praktisch. Dadurch wird jedoch der Unterschied zwischen dem Laden aus Ihrer lokalen
Datenbank (PagingSource) und
Ihrem Netzwerk (RemoteMediator) verschleiert.
Das kann dazu führen, dass in der UI kurz ein Lade-Spinner angezeigt wird, obwohl die Daten im Cache
sofort verfügbar sind.
Wenn Sie eine genaue Steuerung benötigen, z. B. um einen Lade-Spinner nur dann anzuzeigen, wenn die lokale Datenbank leer ist und eine Netzwerksynchronisierung aktiv ist, greifen Sie direkt in Ihrer zusammensetzbaren Funktion auf die Properties source und mediator zu.
val loadState = pagingItems.loadState val isSyncing = loadState.mediator?.refresh is LoadState.Loading val isLocalEmpty = loadState.source.refresh is LoadState.NotLoading && pagingItems.itemSnapshotList.items.isEmpty() if (isSyncing && isLocalEmpty) { FullScreenLoading() } else { UserList(pagingItems) if (isSyncing) { TopOverlaySpinner() } }
Auf Änderungen des Ladestatus reagieren
Möglicherweise müssen Sie einmalige Nebeneffekte auslösen, die auf Änderungen des Ladestatus basieren, z. B. zum Anfang einer Liste scrollen oder eine Snackbar anzeigen, wenn eine Aktualisierung abgeschlossen ist.
Verwenden Sie snapshotFlow in einem LaunchedEffect, um Statusänderungen als Stream zu beobachten. So können Sie Standardoperatoren für Flow wie filter
und distinctUntilChanged anwenden, um bestimmte Ereignisse zu isolieren.
val listState = rememberLazyListState() LaunchedEffect(pagingItems) { // 1. Convert the state to a Flow snapshotFlow { pagingItems.loadState.refresh } // 2. Filter for the specific event (Refresh completed successfully) .distinctUntilChanged() .filter { it is LoadState.NotLoading } .collect { // 3. Trigger the side effect listState.animateScrollToItem(0) } }
Zusätzliche Ressourcen
Weitere Informationen zur Paging-Bibliothek und zu Ladestatus finden Sie in den folgenden Ressourcen.
Dokumentation
Views-Inhalte
Empfehlungen für Sie
- Hinweis: Linktext wird angezeigt, wenn JavaScript deaktiviert ist
- Übersicht über die Paging-Bibliothek