You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 21:05:34