Перейти на страницу 3

Paging 3 значительно отличается от предыдущих версий библиотеки Paging. Эта версия предлагает расширенную функциональность, первоклассную поддержку сопрограмм Kotlin и Flow , а также бесшовную интеграцию с Jetpack Compose.

Преимущества перехода на пейджинг 3

В Paging 3 добавлены следующие функции, отсутствовавшие в более ранних версиях библиотеки:

  • Первоклассная поддержка сопрограмм Kotlin и Flow .
  • Встроенные сигналы состояния загрузки и ошибок для адаптивного дизайна пользовательского интерфейса, включая функции повторной попытки и обновления.
  • Улучшения в уровне репозитория, включая поддержку отмены и упрощенный интерфейс источника данных.
  • Улучшения в уровне представления, разделителях списков, пользовательских преобразованиях страниц, верхних и нижних колонтитулах, а также элементах состояния загрузки для ленивых списков.

Переведите ваше приложение на Paging 3.

Для полного перехода на систему пейджинга 3 необходимо перенести следующие основные компоненты из системы пейджинга 2:

  • Классы DataSource
  • PagedList
  • Слой представления (для LazyPagingItems )

Однако некоторые компоненты Paging 3 обратно совместимы с предыдущими версиями Paging. В частности, API Pager может использовать более старые объекты DataSource с помощью метода asPagingSourceFactory . Это означает, что у вас есть следующие варианты миграции:

  • Вы можете перенести свой DataSource в PagingSource , но оставить остальную часть реализации постраничной навигации без изменений.
  • Вы можете перенести всю реализацию постраничной навигации, чтобы полностью перевести ваше приложение на Paging 3.

В разделах этой страницы объясняется, как перенести компоненты постраничной навигации на каждый уровень вашего приложения.

Классы DataSource

В этом разделе описаны все необходимые изменения для миграции более старой реализации Paging на использование PagingSource .

Классы PageKeyedDataSource , PositionalDataSource и ItemKeyedDataSource из Paging 2 объединены в API PagingSource в Paging 3. Методы загрузки из всех старых классов API объединены в один метод load в PagingSource . Это уменьшает дублирование кода, поскольку большая часть логики в методах загрузки в реализациях старых классов API часто идентична.

В разделе «Страничная навигация 3» все параметры метода загрузки заменяются закрытым классом LoadParams , который включает подклассы для каждого типа загрузки. Если вам необходимо различать типы загрузки в вашем методе load , проверьте, какой подкласс LoadParams был передан: LoadParams.Refresh , LoadParams.Prepend или LoadParams.Append .

Чтобы узнать больше о реализации PagingSource , см. раздел «Определение источника данных» .

Клавиши обновления

Реализации PagingSource должны определять, как возобновляется обновление с середины загруженных постраничных данных. Для этого необходимо реализовать getRefreshKey , который сопоставляет правильный начальный ключ, используя state.anchorPosition в качестве наиболее недавно использованного индекса.

// 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
}

Преобразования списков

В более старых версиях библиотеки Paging преобразование постраничных данных осуществляется с помощью следующих методов:

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

В Paging 3 все преобразования применяются как операторы к PagingData . Если вы используете какой-либо из методов из приведенного выше списка для преобразования вашего постраничного списка, вам необходимо перенести логику преобразования из DataSource в PagingData при создании Pager с использованием вашего нового PagingSource .

Чтобы узнать больше о применении преобразований к постраничным данным с помощью Paging 3, см. раздел «Преобразование потоков данных» .

PagedList

В этом разделе описаны все необходимые изменения для миграции более старой реализации Paging на использование Pager и PagingData в Paging 3.

Классы PagedListBuilder

PagingData заменяет существующий PagedList из Paging 2. Для перехода на PagingData необходимо обновить следующее:

  • Настройка пейджинга перенесена из PagedList.Config в файл PagingConfig .
  • Более старые классы-конструкторы были объединены в один класс Pager .
  • Pager предоставляет наблюдаемый Flow<PagingData> с его свойством .flow .
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)

Чтобы узнать больше о настройке реактивного потока объектов PagingData с использованием Paging 3, см. раздел «Настройка потока PagingData» .

BoundaryCallback для обработки многоуровневых источников

В Paging 3 RemoteMediator заменяет PagedList.BoundaryCallback в качестве обработчика для постраничной навигации из сети и базы данных.

Чтобы узнать больше об использовании RemoteMediator для переадресации страниц из сети и базы данных в Paging 3, см. практическое руководство по Android Paging .

LazyPagingItems

В этом разделе описаны все необходимые изменения для миграции более старой реализации постраничной навигации на использование LazyPagingItems из Paging 3.

Paging 3 предоставляет collectAsLazyPagingItems для обработки нового потока PagingData . Для миграции уровня представления используйте артефакт paging-compose и collectAsLazyPagingItems для сбора элементов PagingData и их отображения в функциях @Composable .

Чтобы узнать больше о LazyPagingItems , см. раздел «Загрузка и отображение постраничных данных» .

Сравнение списков и обновления

Если вы в настоящее время используете собственную логику сравнения списков, перейдите на использование LazyPagingItems предоставляемых в Paging 3. Чтобы гарантировать корректное сравнение, укажите ключ элемента в вашем ленивом списке:

@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)
            }
        }
    }
}

Для получения дополнительной информации о ключах предметов см. раздел «Ключи предметов» .

Состояния загрузки

В Paging 3 вам не нужен отдельный адаптер для отображения заголовков или нижних колонтитулов для состояний загрузки. Объект LazyPagingItems предоставляет свойство loadState , которое вы можете проверить непосредственно в вашем LazyColumn .

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())
        }
    }
}

Дополнительные ресурсы

Чтобы узнать больше о библиотеке пейджинга, ознакомьтесь со следующими дополнительными ресурсами:

Документация

Просмотры контента

{% verbatim %} {% endverbatim %} {% verbatim %} {% endverbatim %}