Migracja do biblioteki Paging 3 (widoki)

Koncepcje i implementacja Jetpack Compose

Biblioteka Paging 3 znacznie różni się od wcześniejszych wersji biblioteki Paging. Ta wersja zapewnia rozszerzoną funkcjonalność i rozwiązuje typowe problemy związane z korzystaniem z biblioteki Paging 2. Jeśli Twoja aplikacja korzysta już z wcześniejszej wersji biblioteki Paging, przeczytaj tę stronę, aby dowiedzieć się więcej o migracji do biblioteki Paging 3.

Jeśli biblioteka Paging 3 jest pierwszą wersją biblioteki Paging, której używasz w swojej aplikacji, podstawowe informacje o korzystaniu z niej znajdziesz w artykule Wczytywanie i wyświetlanie danych podzielonych na strony.

Korzyści z migracji do biblioteki Paging 3

Biblioteka Paging 3 zawiera te funkcje, których nie było we wcześniejszych wersjach biblioteki:

  • Pełna obsługa współprogramów i środowiska Kotlin Flow.
  • Obsługa ładowania asynchronicznego za pomocą typów pierwotnych RxJava Single lub Guava ListenableFuture.
  • Wbudowane sygnały stanu ładowania i błędów umożliwiające projektowanie responsywnego interfejsu, w tym funkcje ponawiania i odświeżania.
  • Ulepszenia warstwy repozytorium, w tym obsługa anulowania i uproszczony interfejs źródła danych.
  • Ulepszenia warstwy prezentacji, separatory list, niestandardowe przekształcenia stron oraz nagłówki i stopki stanu ładowania.

Migracja aplikacji do biblioteki Paging 3

Aby w pełni przejść na bibliotekę Paging 3, musisz przenieść wszystkie 3 główne komponenty z biblioteki Paging 2:

  • klasy DataSource
  • PagedList
  • PagedListAdapter

Niektóre komponenty biblioteki Paging 3 są jednak wstecznie zgodne z poprzednimi wersjami biblioteki Paging. W szczególności interfejs PagingSource z biblioteki Paging 3 może być źródłem danych dla interfejsów LivePagedListBuilder i RxPagedListBuilder ze starszych wersji. Podobnie interfejs Pager może używać starszych DataSource obiektów za pomocą metody asPagingSourceFactory. Oznacza to, że masz te opcje migracji:

  • Możesz przenieść DataSource do PagingSource, ale pozostawić resztę implementacji biblioteki Paging bez zmian.
  • Możesz przenieść PagedList i PagedListAdapter, ale nadal używać starszego interfejsu DataSource API.
  • Możesz przenieść całą implementację biblioteki Paging, aby w pełni przenieść aplikację do biblioteki Paging 3.

W sekcjach na tej stronie dowiesz się, jak przenieść komponenty biblioteki Paging w każdej warstwie aplikacji.

Omówienie migracji

Aby w pełni przejść na bibliotekę Paging 3, zachowując implementację RecyclerView, musisz zaktualizować te komponenty:

Komponent biblioteki Paging 2

Zamiennik w bibliotece Paging 3

PageKeyedDataSource

PagingSource

PagedListAdapter

PagingDataAdapter

LivePagedListBuilder

Pager

BoundaryCallback

RemoteMediator

Klasy DataSource

W tej sekcji opisujemy niezbędne zmiany, które należy wprowadzić, aby przenieść starszą implementację biblioteki Paging do korzystania z interfejsu PagingSource.

Interfejsy PageKeyedDataSource, PositionalDataSource i ItemKeyedDataSource z biblioteki Paging 2 są połączone w interfejs PagingSource w bibliotece Paging 3. Metody ładowania ze wszystkich starych klas interfejsu API są połączone w jedną metodę load w interfejsie PagingSource. Zmniejsza to duplikowanie kodu, ponieważ większość logiki w metodach ładowania w implementacjach starych klas interfejsu API jest często identyczna.

Wszystkie parametry metody ładowania są zastępowane w bibliotece Paging 3 przez klasę zapieczętowaną LoadParams, która zawiera podklasy dla każdego typu ładowania. Jeśli musisz rozróżniać typy ładowania w metodzie load, sprawdź, która podklasa LoadParams została przekazana: LoadParams.Refresh, LoadParams.Prepend, lub LoadParams.Append.

Więcej informacji o implementowaniu interfejsu PagingSource znajdziesz w artykule Definiowanie źródła danych.

Klucze odświeżania

Implementacje interfejsu PagingSource muszą określać, jak odświeżanie ma być wznawiane od środka wczytanych danych podzielonych na strony. Aby to zrobić, zaimplementuj metodę getRefreshKey aby mapować prawidłowy klucz początkowy za pomocą parametru state.anchorPosition jako ostatnio używanego indeksu.

Java (RxJava)

// Replaces ItemKeyedDataSource.
@Nullable
@Override
String getRefreshKey(state: PagingState<String, User>) {
  Integer anchorPosition = state.anchorPosition;
  if (anchorPosition == null) {
    return null;
  }

  return state.getClosestItemToPosition(anchorPosition);
}

// Replaces PositionalDataSource.
@Nullable
@Override
Integer getRefreshKey(state: PagingState<Integer, User>) {
  return state.anchorPosition;
}

Java (Guava/LiveData)

// Replaces ItemKeyedDataSource.
@Nullable
@Override
String getRefreshKey(state: PagingState<String, User>) {
  Integer anchorPosition = state.anchorPosition;
  if (anchorPosition == null) {
    return null;
  }

  return state.getClosestItemToPosition(anchorPosition);
}

// Replaces PositionalDataSource.
@Nullable
@Override
Integer getRefreshKey(state: PagingState<Integer, User>) {
  return state.anchorPosition;
}

PagedList

W tej sekcji opisujemy wszystkie niezbędne zmiany, które należy wprowadzić, aby przenieść starszą implementację biblioteki Paging do korzystania z interfejsu Pager i PagingData w bibliotece Paging 3.

Klasy PagedListBuilder

Interfejs PagingData zastępuje istniejący interfejs PagedList z biblioteki Paging 2. Aby przejść na interfejs PagingData, musisz zaktualizować te elementy:

  • Konfiguracja biblioteki Paging została przeniesiona z interfejsu PagedList.Config do interfejsu PagingConfig.
  • Interfejsy LivePagedListBuilder i RxPagedListBuilder zostały połączone w jedną klasę Pager.
  • Pager udostępnia obserwowalny Flow<PagingData> z jego .właściwością flow. Warianty RxJava i LiveData są też dostępne jako właściwości rozszerzenia, które można wywoływać z Javy za pomocą metod statycznych i które są udostępniane odpowiednio przez moduły paging-rxjava* i paging-runtime.

Java (RxJava)

// CoroutineScope helper provided by the lifecycle-viewmodel-ktx artifact.
CoroutineScope viewModelScope = ViewModelKt.getViewModelScope(viewModel);
Pager<Integer, User> pager = Pager<>(
  new PagingConfig(/* pageSize = */ 20),
  () -> ExamplePagingSource(backend, query));

Flowable<PagingData<User>> flowable = PagingRx.getFlowable(pager);
PagingRx.cachedIn(flowable, viewModelScope);

Java (Guava/LiveData)

// CoroutineScope helper provided by the lifecycle-viewmodel-ktx artifact.
CoroutineScope viewModelScope = ViewModelKt.getViewModelScope(viewModel);
Pager<Integer, User> pager = Pager<>(
  new PagingConfig(/* pageSize = */ 20),
  () -> ExamplePagingSource(backend, query));

PagingLiveData.cachedIn(PagingLiveData.getLiveData(pager), viewModelScope);

Więcej informacji o konfigurowaniu strumienia reaktywnego obiektów PagingData za pomocą biblioteki Paging 3 znajdziesz w artykule Konfigurowanie strumienia PagingData.

PagedListAdapter

W tej sekcji opisujemy wszystkie niezbędne zmiany, które należy wprowadzić, aby przenieść starszą implementację biblioteki Paging do korzystania z klas PagingDataAdapter lub AsyncPagingDataDiffer z biblioteki Paging 3.

Biblioteka Paging 2 używa PagedListAdapter do powiązania PagedList z RecyclerView. W bibliotece Paging 3 interfejs PagingData zastępuje interfejs PagedList.

Biblioteka Paging 3 udostępnia PagingDataAdapter do obsługi nowych PagingData reaktywnych strumieni. W przeciwnym razie interfejsy PagedListAdapter i PagingDataAdapter mają ten sam interfejs. Aby przejść z interfejsu PagedListAdapter na interfejs PagingDataAdapter, zmień implementację interfejsu PagedListAdapter, aby zamiast niego rozszerzać interfejs PagingDataAdapter.

Więcej informacji o interfejsie PagingDataAdapter znajdziesz w artykule Definiowanie adaptera RecyclerView.

AsyncPagedListDiffer

Jeśli obecnie używasz niestandardowej implementacji interfejsu RecyclerView.Adapter z interfejsem AsyncPagedListDiffer, przenieś implementację do korzystania z interfejsu AsyncPagingDataDiffer udostępnianego w bibliotece Paging 3:

Kotlin

AsyncPagingDataDiffer(diffCallback, listUpdateCallback)

Java (RxJava)

new AsyncPagingDataDiffer(diffCallback, listUpdateCallback);

Java (Guava/LiveData)

new AsyncPagingDataDiffer(diffCallback, listUpdateCallback);