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

Android中依赖型异步函数嵌套代码优化咨询

优化依赖型异步任务的结果处理方案

针对Android开发中依赖型异步任务嵌套when导致可读性差的问题,推荐以下几种扁平化的实现方式:

方案一:自定义扩展函数实现链式调用

给MyResult密封类添加扩展函数,让成功/失败的处理逻辑可以链式串联,避免嵌套:

1. 扩展函数定义

sealed class MyResult<out T> {
    data class Success<out T>(val data: T) : MyResult<T>()
    data class Failure(val error: Throwable) : MyResult<Nothing>()
}

// 仅在Success状态时执行后续异步任务
fun <T, R> MyResult<T>.onSuccess(block: (T) -> MyResult<R>): MyResult<R> {
    return when (this) {
        is MyResult.Success -> block(data)
        is MyResult.Failure -> this
    }
}

// 处理Failure状态,支持链式调用
fun <T> MyResult<T>.onFailure(block: (Throwable) -> Unit): MyResult<T> {
    if (this is MyResult.Failure) {
        block(error)
    }
    return this
}

2. 使用示例

function1UseCase.getResult1()
    .onFailure { /* 处理function1执行失败的逻辑 */ }
    .onSuccess { result1Data ->
        function2UseCase.getResult2(result1Data)
    }
    .onFailure { /* 处理function2执行失败的逻辑 */ }
    .onSuccess { result2Data ->
        // 继续执行后续依赖任务,比如function3
    }

方案二:Kotlin协程+分阶段判断

将异步任务改造为挂起函数,在协程中按顺序执行,通过顺序判断替代嵌套:

1. 改造UseCase为挂起函数

suspend fun getResult1(): MyResult<Data1> {
    return try {
        val data = firebaseApi.fetchData1() // 异步操作
        MyResult.Success(data)
    } catch (e: Exception) {
        MyResult.Failure(e)
    }
}

suspend fun getResult2(data1: Data1): MyResult<Data2> {
    return try {
        val data = otherApi.fetchData2(data1) // 依赖data1的异步操作
        MyResult.Success(data)
    } catch (e: Exception) {
        MyResult.Failure(e)
    }
}

2. 协程中执行

viewModelScope.launch {
    // 执行任务1
    val result1 = function1UseCase.getResult1()
    if (result1 is MyResult.Failure) {
        // 处理任务1失败
        return@launch
    }

    // 任务1成功后执行任务2
    val result2 = function2UseCase.getResult2(result1.data)
    if (result2 is MyResult.Failure) {
        // 处理任务2失败
        return@launch
    }

    // 任务2成功后执行后续逻辑
}

如果需要更简洁的异常处理,可给MyResult添加getOrThrow扩展,结合runCatching:

fun <T> MyResult<T>.getOrThrow(): T {
    return when (this) {
        is MyResult.Success -> data
        is MyResult.Failure -> throw error
    }
}

// 使用方式
viewModelScope.launch {
    runCatching {
        val data1 = function1UseCase.getResult1().getOrThrow()
        val data2 = function2UseCase.getResult2(data1).getOrThrow()
        // 后续逻辑
    }.onFailure { e ->
        // 统一处理所有失败(适合无需区分失败阶段的场景)
    }
}

方案三:Flow串联数据流

如果需要处理更复杂的异步数据流(比如持续监听、多阶段任务联动),可使用Kotlin Flow:

1. 改造UseCase返回Flow

fun getResult1Flow(): Flow<MyResult<Data1>> = flow {
    val data = firebaseApi.fetchData1()
    emit(MyResult.Success(data))
}.catch { emit(MyResult.Failure(it)) }

fun getResult2Flow(data1: Data1): Flow<MyResult<Data2>> = flow {
    val data = otherApi.fetchData2(data1)
    emit(MyResult.Success(data))
}.catch { emit(MyResult.Failure(it)) }

2. 串联任务并监听

viewModelScope.launch {
    function1UseCase.getResult1Flow()
        .flatMapConcat { result1 ->
            // 任务1成功则执行任务2,否则直接传递失败结果
            if (result1 is MyResult.Success) {
                function2UseCase.getResult2Flow(result1.data)
            } else {
                flow { emit(result1 as MyResult.Failure) }
            }
        }
        .collect { result ->
            when (result) {
                is MyResult.Success -> { /* 处理最终成功结果 */ }
                is MyResult.Failure -> { /* 根据失败阶段处理逻辑 */ }
            }
        }
}

方案选型建议

  • 链式扩展函数:适合简单的2-3个依赖任务,代码最简洁,扁平化效果明显。
  • 协程分阶段判断:适合需要区分每个任务失败场景的业务逻辑,逻辑清晰易维护。
  • Flow:适合需要数据流监听、多阶段异步联动或生命周期感知的复杂场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 18:37:14