Android Jetpack Paging 3:带 Room 的 PagingSource
Posted
技术标签:
【中文标题】Android Jetpack Paging 3:带 Room 的 PagingSource【英文标题】:Android Jetpack Paging 3: PagingSource with Room 【发布时间】:2020-12-12 19:46:04 【问题描述】:我正在使用最新的 Jetpack 库。
分页3版本:3.0.0-alpha05
房间版:2.3.0-alpha02
我的实体有 Long as PrimaryKey
并且 Room 可以为 Int
以外的类型生成 PagingSource
。
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
,例如docs 建议。
问题是数据刷新,因为 Room 生成的代码处理数据刷新,而我的代码无法处理这种情况。
任何建议如何为Room
实现自定义PagingSource
,同时处理Data Refresh
?
【问题讨论】:
【参考方案1】:由于您有“刷新”场景并使用 Room db,我猜您正在使用 Paging3 和网络+本地 db 模式(使用 Room db 作为本地缓存)。
我在网络 + 本地数据库模式下也遇到过类似的情况。我不确定我是否正确理解了您的问题,或者您的情况与我的情况相同,但我还是会分享我所做的。
我使用的是什么:
分页3:3.0.0-beta01 房间:2.3.0-beta02我所做的是让 Room 库创建 PagingSource(使用 Int
的键),并让 RemoteMediator 处理所有其他情况,例如在刷新和/或追加时从网络获取数据,以及插入获取成功后它们立即进入数据库。
我的dao
函数用于从房间库创建 PagingSource:
@Query("SELECT * FROM article WHERE isUnread = 1")
fun getUnreadPagingSource(): PagingSource<Int, LocalArticle>
在我的例子中,我将 Repository 类定义为在其构造函数中包含 dao
类,以便在创建 Pager 类时从存储库中调用上述函数。
我的自定义 RemoteMediator 类如下所示:
注意:在我的例子中,没有 PREPEND 情况,所以当参数loadType
的值为 LoadType.PREPEND
时,RemoteMediator#load
函数总是返回 true
。
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()
)
我希望它在某种程度上有所帮助..
其他参考资料:
https://developer.android.com/topic/libraries/architecture/paging/v3-network-db https://android-developers.googleblog.com/2020/07/getting-on-same-page-with-paging-3.html https://www.youtube.com/watch?v=1cwqGOku2a4编辑: 再次阅读文档后,我发现the doc明确指出:
RemoteMediator 用于将数据从网络加载到本地数据库。
【讨论】:
您好,感谢您的回复!我记得我没有网络要求,但我需要支持Long
主键,不幸的是Paging3
PagingSource
不支持。我最终为Int
创建了额外的行,为Long
创建了另一行。这样PagingSource
仍然可以使用Int
键。
没有回答这个问题,因为答案没有提到如何实现自定义 PagingSource 或如何使用分页 3 库和 Room 将非整数作为 PrimaryKey 处理。以上是关于Android Jetpack Paging 3:带 Room 的 PagingSource的主要内容,如果未能解决你的问题,请参考以下文章
Android Paging 3 - 从 Jetpack Compose 中的 PagingData<T> 对象获取数据列表
Android Jetpack 学习之旅--> Paging 的使用
Android jetpack的Paging和Room结合使用
如何在 Android Jetpack Compose 中结合使用 LazyColumn stickyHeader 和 Paging?
Android-利用Jetpack-Compose-+Paging3+swiperefresh实现分页加载,下拉上拉效果