Paging3技术求助:优先加载网络数据并结合Room本地数据更新UI
问题:Paging3网络优先加载+Room本地数据自动更新UI的实现困境
需求概述
需要实现优先加载网络数据并结合本地Room数据库的功能,核心要求:
- 每次启动页面都先请求网络,展示后端最新状态
- 本地数据库数据更新时,UI自动同步刷新
使用场景示例
- UserActivity通过Paging3展示某用户的全部已创建帖子,数据来源为网络
- 用户进入PostActivity对某帖子点赞,该操作触发REST请求,返回的更新后帖子存入本地数据库
- 用户返回UserActivity后,能看到该帖子已标记为点赞状态,UI因本地数据库变化自动更新
尝试过的方案及问题
方案一:Room LimitOffsetPagingSource + RemoteMediator
最初认为这是匹配需求的方案,但存在核心缺陷:本地数据库通过网络初始化填充实体后,后续分页的初始请求会以本地数据为起始源,后端数据的更新只有在用户滚动到列表末尾、LimitOffsetPagingSource无更多数据时,才会触发RemoteMediator请求新数据,UI才能感知到变化。
官方示例中给出的解决方法是在分页前删除所有实体:
// clear all tables in the database if (loadType == LoadType.REFRESH) { repoDatabase.remoteKeysDao().clearRemoteKeys() repoDatabase.reposDao().clearRepos() }
但该操作会破坏其他依赖相同实体的页面,例如:
- TopPostsActivity通过分页展示热门帖子
- 用户点击进入UserActivity,分页初始时删除所有实体重新获取数据,但未滚动到底,仅部分实体被重新存储
- 返回TopPostsActivity后看到空列表,必须手动刷新才能恢复显示
方案二:手动合并本地与远程PagingData
使用自定义PagingSource从网络获取数据,同时监听Room数据集变化的Flow,将其转换为PagingData提交给适配器:
Room DAO代码:
@Query("SELECT * FROM post WHERE author_id = :authorId ORDER BY created_at DESC") fun findAllByAuthor(authorId: String): Flow<PostWithAuthor>
合并逻辑代码:
... val localDbFlow = viewModel.repo.dao.findAllByAuthor(viewModel.author.id) .map { PagingData.from(it) } val networkFlow = viewModel.pager.flow val mergedFlow = merge(localDbFlow, networkFlow) flowAndCollectLatest(mergedFlow, Lifecycle.State.CREATED) { adapter.submitData(it) }
该方案可运行,但无法获取LoadState变化——因为PagingData.from(list)生成的是静态数据,其内部实现的LoadState均为固定的非加载状态,导致无法实现SwipeRefreshLayout这类需要LoadState反馈的刷新操作。
我无法自行实现替代Room自动生成的LimitOffsetPagingSource,想知道是否遗漏了关键实现点?
内容的提问来源于stack exchange,提问作者Ahmet K
相关产品推荐
相关产品推荐

