Room数据库更新后LiveData观察无响应问题排查求助
问题修复方案
核心问题原因
你当前使用的Room查询为单次执行逻辑,仅会返回调用查询瞬间的数据库快照,不会监听后续数据库变更。Room的自动数据更新通知能力,需要DAO返回LiveData类型才能生效,你现在用suspend修饰直接返回实体类的写法,调用一次就结束流程,自然无法收到后续数据库更新的推送。
你之前退出页面再进入、旋转设备才会看到更新,是因为这些操作会触发Fragment重建,重新调用了一次查询接口,手动拿到了最新数据,并非LiveData自动推送的更新。
修复步骤
1. 修改DAO层代码
将查询方法的返回值改为LiveData,移除suspend修饰(Room返回LiveData的查询本身就是异步执行,不需要额外协程/线程切换):
@Query("SELECT * FROM cocktail c WHERE c.cocktail_id = :cocktailId") fun getCocktail(cocktailId: Int): LiveData<Cocktail>
2. 修改Repository层代码
不需要再用safeApiCall包装(该工具仅适用单次请求场景),直接返回DAO的LiveData对象:
class CocktailDetailRepository( private val dao: GoodCallDao ):BaseRepository(dao) { fun getCocktail(cocktailId: Int) = dao.getCocktail(cocktailId) }
3. 修改ViewModel层代码
使用数据流转换将Room返回的LiveData包装为你需要的Resource类型,无需再用协程做单次请求:
class CocktailDetailViewModel( private val repository: CocktailDetailRepository ): BaseViewModel(repository) { private val _cocktailId = MutableLiveData<Int>() val cocktail: LiveData<Resource<Cocktail>> = Transformations.switchMap(_cocktailId) { id -> liveData { emit(Resource.Loading) emitSource(repository.getCocktail(id).map { Resource.Success(it) }) } } fun getCocktailByCocktailId(cocktailId: Int) { _cocktailId.value = cocktailId } }
注:上述代码用到的liveData构建器需要引入lifecycle-livedata-ktx依赖,若不使用该依赖,也可通过MediatorLiveData实现相同逻辑。
4. 原有Fragment代码无需改动
观察者逻辑和UI更新逻辑保持原有写法即可,后续数据库中对应鸡尾酒数据变更时,会自动触发观察者回调更新UI。
内容的提问来源于stack exchange,提问作者JBuser
相关产品推荐
相关产品推荐

