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

Android MVI架构ViewModel响应检查代码冗余优化咨询

优化MVI架构ViewModel中HTTP响应处理的冗余代码

核心思路

把重复的HTTP状态码分支逻辑抽成通用处理函数,让ViewModel里的请求函数只聚焦业务数据的转换,不用重复写状态判断逻辑。以下是具体实现方案:


先看原来的冗余代码示例

class MyViewModel(private val repo: MyRepository) : ViewModel() {
    private val _uiState = MutableStateFlow<UiState>(UiState.Idle)
    val uiState = _uiState.asStateFlow()

    fun fetchData() = viewModelScope.launch {
        _uiState.value = UiState.Loading
        val response = repo.fetchData()
        when (response.code) {
            in 200..202 -> _uiState.value = UiState.Success(response.data)
            in 400..499 -> _uiState.value = UiState.Error("客户端错误:${response.message}")
            in 500..599 -> _uiState.value = UiState.Error("服务器错误:${response.message}")
            else -> _uiState.value = UiState.Error("未知错误")
        }
    }

    fun submitData(data: Data) = viewModelScope.launch {
        _uiState.value = UiState.Loading
        val response = repo.submitData(data)
        when (response.code) {
            in 200..202 -> _uiState.value = UiState.SubmitSuccess
            in 400..499 -> _uiState.value = UiState.Error("客户端错误:${response.message}")
            in 500..599 -> _uiState.value = UiState.Error("服务器错误:${response.message}")
            else -> _uiState.value = UiState.Error("未知错误")
        }
    }
}

方案1:封装通用响应处理函数

在ViewModel内部或单独的扩展文件里,写一个通用函数统一处理状态码和UI状态更新:

// 可放在ViewModel基类或扩展文件中
fun <T> ViewModel.handleHttpResponse(
    loadingState: UiState,
    request: suspend () -> HttpResponse<T>,
    onSuccess: (T) -> UiState
) = viewModelScope.launch {
    _uiState.value = loadingState
    try {
        val response = request()
        _uiState.value = when (response.code) {
            in 200..202 -> onSuccess(response.data)
            in 400..499 -> UiState.Error("客户端错误:${response.message}")
            in 500..599 -> UiState.Error("服务器错误:${response.message}")
            else -> UiState.Error("未知错误")
        }
    } catch (e: Exception) {
        _uiState.value = UiState.Error("网络异常:${e.message ?: "未知错误"}")
    }
}

重构后的ViewModel请求函数

class MyViewModel(private val repo: MyRepository) : ViewModel() {
    private val _uiState = MutableStateFlow<UiState>(UiState.Idle)
    val uiState = _uiState.asStateFlow()

    fun fetchData() = handleHttpResponse(
        loadingState = UiState.Loading,
        request = repo::fetchData,
        onSuccess = { UiState.Success(it) }
    )

    fun submitData(data: Data) = handleHttpResponse(
        loadingState = UiState.Loading,
        request = { repo.submitData(data) },
        onSuccess = { UiState.SubmitSuccess }
    )
}

方案2:用Flow封装响应式请求流

如果更贴合Flow的响应式特性,可以把请求封装成Flow,统一处理响应转换:

// 通用HTTP响应转换Flow
fun <T> httpRequestFlow(request: suspend () -> HttpResponse<T>): Flow<UiState> = flow {
    val response = request()
    emit(
        when (response.code) {
            in 200..202 -> UiState.Success(response.data)
            in 400..499 -> UiState.Error("客户端错误:${response.message}")
            in 500..599 -> UiState.Error("服务器错误:${response.message}")
            else -> UiState.Error("未知错误")
        }
    )
}.catch { e ->
    emit(UiState.Error("网络异常:${e.message ?: "未知错误"}"))
}.onStart { emit(UiState.Loading) }

对应ViewModel用法

fun fetchData() = viewModelScope.launch {
    httpRequestFlow(repo::fetchData)
        .collect { _uiState.value = it }
}

fun submitData(data: Data) = viewModelScope.launch {
    httpRequestFlow { repo.submitData(data) }
        .map { 
            // 针对提交成功的特殊状态转换
            if (it is UiState.Success<*>) UiState.SubmitSuccess else it
        }
        .collect { _uiState.value = it }
}

优化后的优势

  • 消除重复:所有状态码判断逻辑集中在一处,后续修改只需调整通用函数
  • 关注点分离:请求函数只需要处理业务相关的UI状态转换,不用管通用响应逻辑
  • 统一异常处理:网络异常、未知错误等都在通用逻辑里处理,避免每个请求写try-catch
  • 扩展性强:后续新增状态码分支(比如3xx重定向),只需修改通用函数即可

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 17:13:09