Android Kotlin:如何获取无关联双Room表数据并通过Retrofit提交?
解决方案
方案一:使用MediatorLiveData合并数据
MediatorLiveData可以监听多个LiveData的变化,当两个数据源都就绪时,将它们封装成一个组合对象,再执行提交操作。
实现步骤:
- 定义封装两个列表的数据类:
data class SubmissionData( val karyawanList: List<KaryawanLocalEntity>, val absenList: List<AbsenEntity> )
- 创建MediatorLiveData合并两个LiveData:
// 临时变量存储两个数据源的最新数据 private var currentKaryawanList: List<KaryawanLocalEntity>? = null private var currentAbsenList: List<AbsenEntity>? = null val combinedData = MediatorLiveData<SubmissionData>().apply { // 监听第一个LiveData addSource(listKaryawanLocalEntity) { list -> currentKaryawanList = list updateCombinedData() } // 监听第二个LiveData addSource(logAllAbsen) { list -> currentAbsenList = list updateCombinedData() } } private fun updateCombinedData() { val karyawan = currentKaryawanList val absen = currentAbsenList // 根据业务需求判断数据是否就绪,比如允许空列表可去掉非空判断 if (karyawan != null && absen != null) { combinedData.value = SubmissionData(karyawan, absen) } }
- 观察合并后的LiveData,发起Retrofit请求:
combinedData.observe(this) { submissionData -> // 用协程在后台执行提交(推荐用lifecycleScope或viewModelScope) lifecycleScope.launch { try { val response = apiService.submitData(submissionData) // 处理成功响应 } catch (e: Exception) { // 处理请求异常 } } }
方案二:使用Flow的combine操作符(推荐,适配现代Kotlin协程)
如果你的Room DAO支持返回Flow(Room 2.2+默认支持),可以将LiveData转为Flow,用combine操作符合并两个数据流,代码更简洁且天然适配协程。
实现步骤:
- 调整Room DAO返回Flow(或直接将现有LiveData转为Flow):
// 示例DAO方法(若之前是LiveData,可改为Flow) @Query("SELECT * FROM karyawan ORDER BY ...") fun getDataDescLocal(): Flow<List<KaryawanLocalEntity>> @Query("SELECT * FROM absen") fun getAllAbsensi(): Flow<List<AbsenEntity>>
- 在ViewModel/Repository中合并两个Flow:
val combinedFlow = combine( repository.local.getDataDescLocal(), repository.local.getAllAbsensi() ) { karyawanList, absenList -> SubmissionData(karyawanList, absenList) }
- 收集Flow数据并提交:
// 在Activity/Fragment的生命周期协程中收集数据 lifecycleScope.launch { combinedFlow.collect { submissionData -> // 根据业务判断是否需要提交(比如避免空数据请求) if (submissionData.karyawanList.isNotEmpty() || submissionData.absenList.isNotEmpty()) { try { val response = apiService.submitData(submissionData) // 处理成功逻辑 } catch (e: Exception) { // 处理错误逻辑 } } } }
注意事项
- 提交前需根据业务规则校验数据有效性,避免无效请求。
- Retrofit请求必须在后台线程执行,务必用协程或其他异步方式,禁止在主线程调用。
- 若仅需单次提交而非实时监听数据变化,可在获取到有效数据后取消观察/收集,避免重复提交。
内容的提问来源于stack exchange,提问作者Denny Zefanya
相关产品推荐
相关产品推荐

