Android中如何合并并等待多个DAO的getData()调用
解决MVVM中并发获取多表数据并等待全部完成的问题
核心问题分析
你当前的DAO方法返回LiveData<List<T>>,LiveData是为UI异步观察设计的,但你需要一次性获取所有表的当前数据,组装成AllData后传给API,因此需要将异步的LiveData转换为可同步等待的挂起函数,并通过协程并发执行多个数据获取任务。
步骤1:将仓库方法转为挂起函数
利用Room与协程的兼容性,将LiveData转换为挂起函数,获取当前数据库的数据快照。修改仓库类中的方法:
// 仓库类示例 class DataRepository( private val dataDaoOne: DataDaoOne, private val dataDaoTwo: DataDaoTwo, // 注入另外3个DAO实例 ) { // 获取ClassA数据的挂起函数 suspend fun getClassAData(): List<ClassA> { return dataDaoOne.getData().first() } // 获取ClassB数据的挂起函数 suspend fun getClassBData(): List<ClassB> { return dataDaoTwo.getData().first() } // 为另外3个DAO实现相同结构的挂起函数 // suspend fun getClassCData(): List<ClassC> = dataDaoThree.getData().first() // ... }
first()方法会挂起协程,直到LiveData发射第一个值(即当前数据库中的数据),之后立即返回该值。
步骤2:并发获取所有数据并组装AllData
使用协程的async和await实现并发任务,等待所有数据加载完成后组装成AllData:
// 完整的AllData数据类 data class AllData( val classA: List<ClassA>, val classB: List<ClassB>, val classC: List<ClassC>, val classD: List<ClassD>, val classE: List<ClassE> ) // 异步获取并组装所有数据的挂起函数 suspend fun getAllData(repository: DataRepository): AllData { return coroutineScope { // 启动5个并发的数据获取任务 val taskA = async { repository.getClassAData() } val taskB = async { repository.getClassBData() } val taskC = async { repository.getClassCData() } val taskD = async { repository.getClassDData() } val taskE = async { repository.getClassEData() } // 等待所有任务完成,组装结果 AllData( classA = taskA.await(), classB = taskB.await(), classC = taskC.await(), classD = taskD.await(), classE = taskE.await() ) } }
coroutineScope会保证:如果任一任务抛出异常,所有并发任务都会被取消,避免出现部分数据加载成功、部分失败的不一致状态。
步骤3:在协程上下文调用方法
由于getAllData()是挂起函数,必须在协程中调用(比如ViewModel的viewModelScope、Activity/Fragment的lifecycleScope):
// 示例:在ViewModel中调用 class MainViewModel( private val repository: DataRepository ) : ViewModel() { fun uploadAllData() { viewModelScope.launch { try { val allData = getAllData(repository) sendDataToServer(allData) } catch (e: Exception) { // 处理数据加载或API调用失败的异常 } } } // 假设的API调用函数 private suspend fun sendDataToServer(allData: AllData) { // 实现你的API请求逻辑 } }
内容的提问来源于stack exchange,提问作者Takshak Rajput
相关产品推荐
相关产品推荐

