Android MVI架构下Room数据库数据自动更新问题解决
解决Room数据更新后RecyclerView自动刷新问题(MVI架构)
问题根源
当前Dao返回的是MutableList<Entity>,这是一次性获取的数据快照,无法监听数据库的后续变化。Room原生支持返回Flow<List<Entity>>,当数据库发生插入/更新/删除操作时,Flow会自动发射最新的数据集,以此实现实时更新。
分步修改代码
1. 修改Dao层
将getAllData()的返回类型改为Flow<List<Entity>>,Room会自动处理数据变化的监听逻辑:
@Query("SELECT * FROM my_table") fun getAllData(): Flow<List<Entity>>
2. 修改Repository层
对应Dao的返回类型,同步更新allData()的返回值:
class MyRepository @Inject constructor(private val dao: DataDao) { fun allData() = dao.getAllData() }
3. 修改ViewModel层
移除手动触发加载的Intent逻辑,直接在ViewModel初始化时收集数据Flow,数据库变化时自动更新StateFlow:
@HiltViewModel class MyViewModel @Inject constructor(private val repository: MyRepository) : ViewModel() { private val _state = MutableStateFlow<MainState>(MainState.Idle) val state: StateFlow<MainState> get() = _state init { observeDataChanges() } private fun observeDataChanges() { viewModelScope.launch { repository.allData().collect { dataList -> _state.value = MainState.LoadData(dataList) } } } }
说明:若需保留Intent处理其他业务逻辑,可保留原有
mainIntent代码,但加载数据的逻辑无需再通过Intent触发。
4. 修改Activity层
仅需收集ViewModel的state流,数据变化时自动更新Adapter,无需手动发送LoadAllData Intent:
// 建议将RecyclerView初始化逻辑移至onCreate,避免重复执行 override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) fataList.apply { layoutManager = StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL) adapter = dataAdapter } lifecycleScope.launch { viewModel.state.collect { state -> when (state) { is MainState.Idle -> {} is MainState.LoadData -> dataAdapter.setData(state.list) } } } }
优化点:RecyclerView的布局管理器和Adapter初始化只需执行一次,移至
onCreate可提升性能。
关键原理
Room的Flow查询会在目标表数据发生变化时自动重新执行查询,并将最新结果发射到Flow中。ViewModel持续收集这个Flow并更新StateFlow,Activity监听StateFlow的状态变化,最终实现数据更新后自动刷新RecyclerView,无需重启应用。
内容的提问来源于stack exchange,提问作者Dr.KeyOk
相关产品推荐
相关产品推荐

