Android Jetpack Paging 3: PagingSource с комнатой

Я использую последние библиотеки Jetpack.
Версия Pagination3:3.0.0-alpha05
Версия комнаты: 2.3.0-alpha02

Мои сущности уже давно PrimaryKey и Room может генерировать PagingSource для кроме Int тип.

error: For now, Room only supports PagingSource with Key of type Int.
    public abstract androidx.paging.PagingSource<java.lang.Long, com.example.myEntity>` getPagingSource();

Поэтому я попытался реализовать свой собственный PagingSource, как предлагают документы.

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

Любые предложения, как реализовать индивидуальный PagingSource за Room это также обрабатывает Data Refresh?

1 ответ

Поскольку у вас есть сценарий обновления и используется Room db, я предполагаю, что вы используете Paging3 с шаблоном сеть + локальный db (с Room db в качестве локального кеша).

У меня была аналогичная ситуация с шаблоном сеть + локальная база данных. Я не уверен, правильно ли я понял ваш вопрос, или ваша ситуация такая же, как у меня, но я все равно поделюсь тем, что я сделал.

Что я использовал:

  • Paging3: 3.0.0-beta01
  • Комната: 2.3.0-beta02

Я позволил библиотеке Room создать PagingSource (с ключом Int), и пусть RemoteMediator обрабатывает все остальные случаи, такие как выборка данных из сети при обновлении и / или добавлении и вставка их в базу данных сразу после успешной выборки.

Моя функция для создания PagingSource из библиотеки комнат:

      @Query("SELECT * FROM article WHERE isUnread = 1")
fun getUnreadPagingSource(): PagingSource<Int, LocalArticle>

В моем случае я определил класс репозитория как daoclass в своем конструкторе для вызова указанной выше функции из репозитория при создании класса Pager .

Мой собственный класс RemoteMediator выглядит примерно так:

  • Примечание: в моем случае нет случая PREPEND, поэтому RemoteMediator#load функция всегда возвращает true когда значение аргумента loadType является LoadType.PREPEND.
      class FeedMediator(
    private val repository: FeedRepository
) : RemoteMediator<Int, LocalArticle>() {

    ... 

    override suspend fun load(
        loadType: LoadType,
        state: PagingState<Int, LocalArticle>
    ): MediatorResult = runCatching {
        when (loadType) {
            LoadType.PREPEND -> true
            LoadType.REFRESH -> {
                feedRepository.refresh()
                false
            }
            LoadType.APPEND -> {
                val continuation = feedRepository.continuation()
                if (continuation.isNullOrEmpty()) {
                    true
                } else {
                    loadFeedAndCheckContinuation(continuation)
                }
            }
        }
    }.fold(
        onSuccess = { endOfPaginationReached -> MediatorResult.Success(endOfPaginationReached) },
        onFailure = {
            Timber.e(it)
            MediatorResult.Error(it)
        }
    )

    private suspend fun loadFeedAndCheckContinuation(continuation: String?): Boolean {
        val feed = feedRepository.load(continuation)
        feedRepository.insert(feed)
        return feed.continuation.isNullOrEmpty()
    }

Наконец вы можете создать Pager учебный класс.

      fun createFeedPager(
        mediator: FeedMediator<Int, LocalArticle>,
        repository: FeedRepository
    ) = Pager(
        config = PagingConfig(
            pageSize = FETCH_FEED_COUNT,
            enablePlaceholders = false,
            prefetchDistance = PREFETCH_DISTANCE
        ),
        remoteMediator = mediator,
        pagingSourceFactory = { repository.getUnreadPagingSource() }
    )

Надеюсь, это поможет ...

Другие ссылки:

Другие вопросы по тегам