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>
В моем случае я определил класс репозитория как
dao
class в своем конструкторе для вызова указанной выше функции из репозитория при создании класса 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() }
)
Надеюсь, это поможет ...
Другие ссылки: