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

如何基于首个返回值条件组合LiveData/Flow,封装带泛型数据的Status状态

实现思路

你可以通过Jetpack提供的MediatorLiveData实现两个LiveData的条件组合,核心逻辑是:

  • 缓存两个LiveData的最新发射值
  • 状态流发射非成功状态时直接透传对应状态
  • 仅当状态流为Success时,才把最新的业务数据包装成Status.Success<T>向下发射

具体实现代码

第一步:引入依赖(如未引入)

在模块build.gradle中添加LiveData KTX依赖:

implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.6.2"

第二步:编写通用组合扩展函数

import androidx.lifecycle.MediatorLiveData
import androidx.lifecycle.LiveData

fun <T> combineStatusWithData(
    statusLiveData: LiveData<Status<Unit>>,
    dataLiveData: LiveData<T>
): LiveData<Status<T>> = MediatorLiveData<Status<T>>().apply {
    // 缓存两个流的最新值
    var latestStatus: Status<Unit>? = null
    var latestData: T? = null

    // 监听状态流更新
    addSource(statusLiveData) { status ->
        latestStatus = status
        refreshCombinedValue()
    }

    // 监听业务数据流更新
    addSource(dataLiveData) { data ->
        latestData = data
        refreshCombinedValue()
    }

    // 统一处理组合逻辑
    fun refreshCombinedValue() {
        when (val currentStatus = latestStatus) {
            is Status.Loading -> value = Status.loading(currentStatus.message)
            is Status.Failure -> value = Status.failed(currentStatus.message)
            is Status.Success -> {
                latestData?.let { data ->
                    value = Status.success(data)
                }
                // 若存在成功状态先触发、数据还未返回的间隙,可打开下方注释避免空白状态
                // ?: run { value = Status.loading("正在加载数据") }
            }
            null -> { /* 状态未初始化,不发射事件 */ }
        }
    }
}

第三步:在ViewModel中调用

class MyViewModel(private val workerContract: IWorkerContract<*, T>) : ViewModel() {
    val myCombinedState: LiveData<Status<T>> = combineStatusWithData(
        statusLiveData = workerContract.workInfo,
        dataLiveData = workerContract.appDatabaseData
    )
}

可选Flow实现方案

如果你的项目已经适配Kotlin Flow,实现逻辑更简洁:

import androidx.lifecycle.asFlow
import androidx.lifecycle.asLiveData
import kotlinx.coroutines.flow.combine

class MyViewModel(private val workerContract: IWorkerContract<*, T>) : ViewModel() {
    val myCombinedState = combine(
        workerContract.workInfo.asFlow(),
        workerContract.appDatabaseData.asFlow()
    ) { status, data ->
        when (status) {
            is Status.Loading -> Status.loading<T>(status.message)
            is Status.Failure -> Status.failed<T>(status.message)
            is Status.Success -> Status.success(data)
        }
    }.asLiveData()
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 17:57:03