Android MVVM架构下:协程+Room结合枚举状态的数据加载实现咨询
实现方案与代码示例
1. 定义加载状态枚举类
先明确状态枚举,对应你需求中的三种状态:
enum class DataLoadState { NEUTRAL, // 初始未加载状态 LOADING, // 数据加载中 AVAILABLE // 数据已就绪 }
2. ViewModel协程实现(分两种Dao返回类型)
ViewModel中必须使用viewModelScope管理协程——它会在ViewModel销毁时自动取消协程,避免内存泄漏。以下分两种常见Dao返回场景实现:
场景1:Dao返回LiveData(Room自动后台查询)
如果你的Dao定义为返回LiveData<List<ResultFile>>(Room会自动在后台线程执行查询,并在数据就绪时回调):
class ResultViewModel(private val resultDao: ResultFileDao) : ViewModel() { // 对外暴露的加载状态LiveData private val _loadState = MutableLiveData<DataLoadState>().apply { value = DataLoadState.NEUTRAL } val loadState: LiveData<DataLoadState> = _loadState // 数据库返回的结果列表LiveData(Room自动监听数据变化) val resultList: LiveData<List<ResultFile>> = resultDao.getAllResults() init { observeDataLoadCompletion() } // 监听数据加载完成时机 private fun observeDataLoadCompletion() { resultList.observeForever { resultFiles -> when { resultFiles == null -> _loadState.value = DataLoadState.LOADING else -> _loadState.value = DataLoadState.AVAILABLE } } } // 手动触发数据刷新(可选,比如插入新结果后调用) fun refreshResults() { _loadState.value = DataLoadState.LOADING // 由于Room的LiveData会自动更新,此处无需额外协程操作,等待Room自动回调即可 } }
场景2:Dao返回suspend函数(手动控制协程)
如果你的Dao定义为返回suspend List<ResultFile>,需要手动通过协程执行查询:
class ResultViewModel(private val resultDao: ResultFileDao) : ViewModel() { private val _loadState = MutableLiveData<DataLoadState>().apply { value = DataLoadState.NEUTRAL } val loadState: LiveData<DataLoadState> = _loadState private val _resultList = MutableLiveData<List<ResultFile>>() val resultList: LiveData<List<ResultFile>> = _resultList init { loadResults() } // 加载数据的协程方法 fun loadResults() { _loadState.value = DataLoadState.LOADING viewModelScope.launch(Dispatchers.IO) { // 在IO线程执行数据库查询 val results = resultDao.getAllResults() // 切换回主线程更新UI数据与状态 withContext(Dispatchers.Main) { _resultList.value = results _loadState.value = DataLoadState.AVAILABLE } } } }
3. 判断数据加载完成的逻辑
- Dao返回LiveData场景:Room的LiveData会在数据库查询完成后,将全量结果回调到观察者中,第一次
observeForever的回调就是所有行数据加载完成的时刻,此时将状态切换为AVAILABLE即可。 - Dao返回suspend函数场景:协程中成功获取到
results并切换到主线程更新_resultList的时刻,就是数据加载完成的节点,同步更新状态为AVAILABLE。
4. UI层(Fragment/Activity)适配示例
// 在Fragment中绑定ViewModel并处理状态 viewModel.loadState.observe(viewLifecycleOwner) { state -> when(state) { DataLoadState.NEUTRAL -> { // 初始状态,显示空白或默认布局 } DataLoadState.LOADING -> { // 显示加载动画/进度条 } DataLoadState.AVAILABLE -> { // 隐藏加载控件,更新RecyclerView数据 viewModel.resultList.observe(viewLifecycleOwner) { results -> yourAdapter.submitList(results) } } } }
内容的提问来源于stack exchange,提问作者Takayuki Furuichi
相关产品推荐
相关产品推荐

