Paging 3 RemoteMediator结合SavedStateHandle解决进程死亡后数据刷新问题
解决Paging 3 RemoteMediator进程恢复后强制刷新问题
问题根因
默认情况下RemoteMediator的initialize()方法会返回InitializeAction.LAUNCH_INITIAL_REFRESH,每次Pager实例创建时(包括进程死亡重建后页面恢复的场景),都会自动触发一次REFRESH类型的远程加载,拉取最新数据覆盖本地已有缓存,这就是你遇到的重复刷新问题的来源。
适配方案
你可以通过重写initialize()方法,根据本地持久化缓存的状态决定是否跳过初始化刷新,具体实现步骤如下:
- 首先在本地持久层(通常是Room)存储每个查询对应的两个状态:已缓存的数据集、对应分页键,也可以按需增加缓存更新时间戳用于过期判断
- 重写
RemoteMediator的initialize()方法,判断当前查询是否有有效缓存,有缓存就返回InitializeAction.SKIP_INITIAL_REFRESH跳过初始化刷新,没有缓存再走正常的首次加载逻辑
代码示例
RemoteMediator 实现
class CustomRemoteMediator( private val query: String, private val database: AppDatabase, private val api: ApiService ) : RemoteMediator<Int, DataItem>() { override suspend fun initialize(): InitializeAction { // 方式1:通过统计当前query对应的本地缓存数据量判断是否有有效缓存 val localDataCount = database.dataDao().countByQuery(query) val hasValidCache = localDataCount > 0 // 方式2:通过当前query对应的分页键是否存在判断是否有有效缓存 // val nextPageKey = database.remoteKeyDao().getNextKeyByQuery(query) // val hasValidCache = nextPageKey != null // 按需增加缓存过期判断逻辑 // val cacheTime = database.cacheDao().getCacheUpdateTime(query) // val isCacheValid = (System.currentTimeMillis() - cacheTime) < 24 * 60 * 60 * 1000 // val hasValidCache = nextPageKey != null && isCacheValid return if (hasValidCache) { // 存在有效缓存,跳过初始化刷新,直接读取本地数据展示 InitializeAction.SKIP_INITIAL_REFRESH } else { // 无有效缓存,触发首次刷新拉取数据 InitializeAction.LAUNCH_INITIAL_REFRESH } } // load方法保持原有实现即可 override suspend fun load( loadType: LoadType, state: PagingState<Int, DataItem> ): MediatorResult { // 你的原有分页加载逻辑 } }
上层代码调整
你原有ViewModel层的代码不需要做任何修改,initialize的逻辑完全在RemoteMediator内部处理,上层无感知。
注意事项
- 所有本地查询操作都要带上query参数做过滤,避免不同搜索词的缓存状态混判
- 如果有缓存过期需求,只需在
initialize的判断逻辑里增加时间戳校验即可,无需改动其他逻辑
内容的提问来源于stack exchange,提问作者Mihirrai
相关产品推荐
相关产品推荐

