Compose+Paging3场景下:Room数据库更新时如何正确刷新PagingSource并同步UI?
Compose+Paging3场景下:Room数据库更新时如何正确刷新PagingSource并同步UI?
嘿,我看你遇到了Paging3配合Room做数据更新时的UI同步问题,还触发了那个烦人的IllegalStateException,我来帮你一步步解决~
先搞懂错误原因
你收到的错误提示已经说得很清楚了:Pager期望每次都创建新的PagingSource实例,但你现在的pagingSourceFactory每次返回的都是同一个实例(直接引用了repository.articlesPaged这个属性),这就违反了Paging3的设计要求,所以直接报错了。
解决方案分两步走
1. 调整Repository,确保每次能获取新的PagingSource
首先你的Repository里不能直接持有PagingSource的实例,应该改成一个函数,每次调用都从Dao获取新的实例:
// 调整后的ArticleRepository示例 class ArticleRepository @Inject constructor( private val articleDao: ArticleDao ) { // 改成函数,每次调用都返回新的PagingSource fun getArticlesPaged(): PagingSource<Int, ArticleEntity> { return articleDao.getAllArticlesPaged() } suspend fun addArticle(articleEntity: ArticleEntity) { articleDao.addArticle(articleEntity) } }
2. 修正UseCase里的pagingSourceFactory
接下来在你的ArticlePagedUseCase里,让pagingSourceFactory每次都调用Repository的函数来获取新实例,而不是直接引用属性:
class ArticlePagedUseCase @Inject constructor( private val repository: ArticleRepository ) { operator fun invoke(): Flow<PagingData<ArticleEntity>> { Log.d("GoogleIO","Invalidate Paging 3") return Pager( config = PagingConfig( pageSize = 20, prefetchDistance = 40 ), // 这里改成函数调用,每次都生成新的PagingSource pagingSourceFactory = { repository.getArticlesPaged() } ).flow } suspend fun addArticle(articleEntity: ArticleEntity) { delay(1000) repository.addArticle(articleEntity) } }
关于Room数据更新后的自动刷新
其实Room和Paging3已经做了联动优化:当你调用addArticle插入新数据后,Room会自动通知对应的PagingSource数据发生了变化,PagingSource会被标记为invalid。这时候Pager会通过你修正后的pagingSourceFactory创建新的PagingSource实例,重新加载最新数据,最终你的Flow会发射新的PagingData,只要Compose这边正常收集这个Flow并渲染UI,就能自动看到新添加的内容啦~
验证一下
现在你每10秒添加新文章后,应该不会再触发那个异常,而且UI会自动同步显示最新的列表内容。
备注:内容来源于stack exchange,提问作者Neeraj Verma
相关产品推荐
相关产品推荐

