Zu Paging 3 migrieren

Paging 3 unterscheidet sich erheblich von früheren Versionen der Paging-Bibliothek. Diese Version bietet erweiterte Funktionen, erstklassige Unterstützung für Kotlin-Coroutinen und Flow sowie eine nahtlose Integration mit Jetpack Compose.

Vorteile der Migration zu Paging 3

Paging 3 enthält die folgenden Funktionen, die in früheren Versionen der Bibliothek nicht vorhanden waren:

  • Erstklassige Unterstützung für Kotlin-Coroutinen und Flow.
  • Integrierte Ladezustands- und Fehlersignale für ein reaktionsschnelles UI-Design, einschließlich Funktionen für Wiederholung und Aktualisierung.
  • Verbesserungen an der Repository-Ebene, einschließlich Unterstützung für die Abbruchfunktion und einer vereinfachten Datenquellenoberfläche.
  • Verbesserungen an der Präsentationsebene, Listentrennzeichen, benutzerdefinierte Seitentransformationen, Kopf- und Fußzeilen sowie Elemente für den Ladestatus für Lazy-Listen.

Anwendung zu Paging 3 migrieren

Für eine vollständige Migration zu Paging 3 müssen Sie die folgenden Hauptkomponenten von Paging 2 migrieren:

  • DataSource-Klassen
  • PagedList
  • Präsentationsebene (zu LazyPagingItems)

Einige Paging 3-Komponenten sind jedoch abwärtskompatibel mit früheren Versionen von Paging. Insbesondere kann die Pager API ältere DataSource Objekte mit der asPagingSourceFactory Methode verwenden. Das bedeutet, dass Sie die folgenden Migrationsoptionen haben:

  • Sie können Ihre DataSource zu PagingSource migrieren, aber den Rest Ihrer Paging-Implementierung unverändert lassen.
  • Sie können die gesamte Paging-Implementierung migrieren, um Ihre Anwendung vollständig zu Paging 3 zu migrieren.

In den Abschnitten auf dieser Seite wird erläutert, wie Sie Paging-Komponenten auf jeder Ebene Ihrer Anwendung migrieren.

DataSource-Klassen

In diesem Abschnitt werden alle erforderlichen Änderungen beschrieben, um eine ältere Paging-Implementierung zu migrieren, damit PagingSource verwendet wird.

PageKeyedDataSource, PositionalDataSource und ItemKeyedDataSource aus Paging 2 werden in Paging 3 in der PagingSource-API kombiniert. Die Lademethoden aus allen alten API-Klassen werden in PagingSource in einer einzigen load-Methode kombiniert. Dadurch wird die Codeduplizierung reduziert, da ein Großteil der Logik in den Lademethoden in Implementierungen der alten API-Klassen oft identisch ist.

Alle Parameter der Lademethode werden in Paging 3 durch eine versiegelte LoadParams-Klasse ersetzt, die Unterklassen für jeden Ladetyp enthält. Wenn Sie in Ihrer load Methode zwischen Ladetypen unterscheiden müssen, prüfen Sie, welche abgeleitete Klasse von LoadParams übergeben wurde: LoadParams.Refresh, LoadParams.Prepend oder LoadParams.Append.

Weitere Informationen zur Implementierung von PagingSource finden Sie unter Datenquelle definieren.

Aktualisierungsschlüssel

Implementierungen von PagingSource müssen definieren, wie Aktualisierungen ab der Mitte der geladenen Seiten-Daten fortgesetzt werden. Implementieren Sie dazu getRefreshKey um den richtigen anfänglichen Schlüssel mit state.anchorPosition als zuletzt aufgerufenen Index zuzuordnen.

// Replaces ItemKeyedDataSource.
override fun getRefreshKey(state: PagingState<String, User>): String? {
  return state.anchorPosition?.let { anchorPosition ->
    state.getClosestItemToPosition(anchorPosition)?.id
  }
}

// Replacing PositionalDataSource.
override fun getRefreshKey(state: PagingState<Int, User>): Int? {
  return state.anchorPosition
}

Listentransformationen

In niedrigeren Versionen der Paging-Bibliothek basiert die Transformation der Seiten-Daten auf den folgenden Methoden:

  • DataSource.map
  • DataSource.mapByPage
  • DataSource.Factory.map
  • DataSource.Factory.mapByPage

In Paging 3 werden alle Transformationen als Operatoren auf PagingData angewendet. Wenn Sie eine der Methoden in der vorherigen Liste verwenden, um Ihre Seitenliste zu transformieren, müssen Sie Ihre Transformationslogik von DataSource zu PagingData verschieben, wenn Sie Pager mit Ihrer neuen PagingSource erstellen.

Weitere Informationen zum Anwenden von Transformationen auf Seiten-Daten mit Paging 3 finden Sie unter Datenstreams transformieren.

PagedList

In diesem Abschnitt werden alle erforderlichen Änderungen beschrieben, um eine ältere Paging-Implementierung zu migrieren, damit Pager und PagingData in Paging 3 verwendet werden.

PagedListBuilder-Klassen

PagingData ersetzt die vorhandene PagedList aus Paging 2. Wenn Sie zu PagingData migrieren möchten, müssen Sie Folgendes aktualisieren:

  • Die Paging-Konfiguration wurde von PagedList.Config zu PagingConfig verschoben.
  • Ältere Builder-Klassen wurden in einer einzigen Pager-Klasse kombiniert.
  • Pager stellt mit der Eigenschaft .flow einen beobachtbaren Flow<PagingData> bereit.
val flow = Pager(
  // Configure how data is loaded by passing additional properties to
  // PagingConfig, such as prefetchDistance.
  PagingConfig(pageSize = 20)
) {
  ExamplePagingSource(backend, query)
}.flow
  .cachedIn(viewModelScope)

Weitere Informationen zum Einrichten eines reaktiven Streams von PagingData Objekten mit Paging 3 finden Sie unter Stream von PagingData einrichten.

BoundaryCallback für mehrschichtige Quellen

In Paging 3 ersetzt RemoteMediator PagedList.BoundaryCallback als Handler für das Paging aus dem Netzwerk und der Datenbank.

Weitere Informationen zur Verwendung von RemoteMediator für das Paging aus dem Netzwerk und der Datenbank in Paging 3 finden Sie im Android Paging-Codelab.

LazyPagingItems

In diesem Abschnitt werden alle erforderlichen Änderungen beschrieben, um eine ältere Paging-Implementierung zu migrieren, damit LazyPagingItems aus Paging 3 verwendet wird.

Paging 3 bietet collectAsLazyPagingItems zur Verarbeitung des neuen PagingData-Flows. Wenn Sie Ihre Präsentationsebene migrieren möchten, verwenden Sie das paging-compose-Artefakt und collectAsLazyPagingItems, um PagingData-Elemente zu erfassen und in @Composable-Funktionen anzuzeigen.

Weitere Informationen zu LazyPagingItems finden Sie unter Seiten-Daten laden und anzeigen.

Listendifferenzierung und ‑aktualisierungen

Wenn Sie derzeit eine benutzerdefinierte Logik zur Listendifferenzierung verwenden, migrieren Sie Ihre Implementierung stattdessen zu LazyPagingItems, das in Paging 3 bereitgestellt wird. Damit die Differenzierung ordnungsgemäß erfolgt, geben Sie einen Elementschlüssel für Ihre Lazy-Liste an:

@Composable
fun UserScreen(viewModel: UserViewModel) {
    // Collects the Flow into a LazyPagingItems object
    val lazyPagingItems = viewModel.pager.flow.collectAsLazyPagingItems()

    UserList(lazyPagingItems)
}

@Composable
fun UserScreen(viewModel: UserViewModel) {
    val lazyPagingItems = viewModel.pager.flow.collectAsLazyPagingItems()

    UserList(lazyPagingItems)
}

@Composable
fun UserList(lazyPagingItems: LazyPagingItems<User>) {
    LazyColumn {
        items(
            count = lazyPagingItems.itemCount,
            // Provide a stable key for each item, similar to DiffUtil in Views
            key = lazyPagingItems.itemKey { user -> user.id } 
        ) { index ->
            val user = lazyPagingItems[index]
            if (user != null) {
                UserRow(user = user)
            }
        }
    }
}

Weitere Informationen zu Elementschlüsseln finden Sie unter Elementschlüssel.

Ladestatus

In Paging 3 benötigen Sie keinen separaten Adapter, um Kopf- oder Fußzeilen für Ladestatus anzuzeigen. Das LazyPagingItems-Objekt stellt eine loadState-Eigenschaft bereit, die Sie direkt in Ihrer LazyColumn prüfen können.

LazyColumn {
    // ... items(lazyPagingItems) go here ...

    // Show loading spinner at bottom of list when appending data
    if (lazyPagingItems.loadState.append is LoadState.Loading) {
        item {
            CircularProgressIndicator(modifier = Modifier.fillMaxWidth())
        }
    }
}

Zusätzliche Ressourcen

Weitere Informationen zur Paging-Bibliothek finden Sie in den folgenden zusätzlichen Ressourcen:

Dokumentation

Inhalte ansehen