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

如何观察多个LiveData的状态,确认两次API请求均加载成功?

实现方案

可以使用Jetpack提供的MediatorLiveData合并两个请求的状态,只需监听这一个合并后的LiveData即可判断是否两个请求都成功。

第一步:修正现有LiveData类型

你当前定义的data1和data2类型声明存在问题,需要调整为包裹DataState的类型:

val data1 = MutableLiveData<DataState<List<Model1>>>()
val data2 = MutableLiveData<DataState<List<Model2>>>()

第二步:定义合并状态的LiveData

在ViewModel中新增MediatorLiveData,可以额外定义一个数据类封装两个请求的成功结果:

// 可选:封装两个接口都成功时的返回数据
data class AllDataResult(
    val data1: List<Model1>,
    val data2: List<Model2>
)

val allDataState = MediatorLiveData<DataState<AllDataResult>>()

init {
    // 把两个请求的LiveData都作为源添加到MediatorLiveData中
    allDataState.addSource(data1) { combineStates() }
    allDataState.addSource(data2) { combineStates() }
    
    getData1()
    getData2()
}

private fun combineStates() {
    val state1 = data1.value
    val state2 = data2.value

    // 只要有一个还在加载,整体状态为加载中
    if (state1 is DataState.Loading || state2 is DataState.Loading) {
        allDataState.value = DataState.Loading
        return
    }

    // 只要有一个报错,整体状态为报错
    if (state1 is DataState.Error) {
        allDataState.value = DataState.Error(state1.exception)
        return
    }
    if (state2 is DataState.Error) {
        allDataState.value = DataState.Error(state2.exception)
        return
    }

    // 两个都成功,返回合并后的结果
    if (state1 is DataState.Success && state2 is DataState.Success) {
        allDataState.value = DataState.Success(
            AllDataResult(
                data1 = state1.data,
                data2 = state2.data
            )
        )
    }
}

第三步:页面层监听逻辑

在Activity/Fragment中只需要监听allDataState这一个LiveData即可:

viewModel.allDataState.observe(this) { state ->
    when(state) {
        is DataState.Loading -> {
            // 展示进度条
            progressBar.visibility = View.VISIBLE
        }
        is DataState.Error -> {
            // 隐藏进度条,展示错误提示
            progressBar.visibility = View.GONE
            Toast.makeText(context, state.exception.message, Toast.LENGTH_SHORT).show()
        }
        is DataState.Success -> {
            // 隐藏进度条,渲染两个接口的返回数据
            progressBar.visibility = View.GONE
            renderData1(state.data.data1)
            renderData2(state.data.data2)
        }
    }
}

其他可选方案

如果你不需要在ViewModel中保留两个接口的单独状态,也可以直接用async并发请求后合并结果,代码更简洁:

val allDataState = MutableLiveData<DataState<AllDataResult>>()

init {
    getAllData()
}

private fun getAllData() {
    viewModelScope.launch {
        allDataState.postValue(DataState.Loading)
        try {
            // 并发请求两个接口
            val data1Deferred = async { repository.getData1().data!! }
            val data2Deferred = async { repository.getData2().data!! }
            
            val result = AllDataResult(
                data1 = data1Deferred.await(),
                data2 = data2Deferred.await()
            )
            allDataState.postValue(DataState.Success(result))
        } catch (e: Exception) {
            allDataState.postValue(DataState.Error(e))
        }
    }
}

这种方式不需要单独维护data1和data2两个LiveData,适合不需要单独使用单个接口返回结果的场景。

内容的提问来源于stack exchange,提问作者farfalletonde

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 14:45:04