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

Kotlin中如何处理Retrofit成功与错误两种不同响应结构?

结论

强烈建议使用sealed class(密封类)实现对应逻辑,不要合并为单个data class

合并为单个data class的弊端

你示例的合并写法存在严重的设计缺陷:

  • 成功响应不含detail字段、错误响应不含access_token和token_type字段,你写的Auth类所有字段均为非空类型,任何一种响应返回时都会因为缺失字段触发序列化失败,直接导致App崩溃
  • 即使将所有字段改为可空类型,后续业务逻辑处理时需要反复做非空校验,既冗余也容易因误判产生空指针异常,无法利用Kotlin的空安全特性
  • 两种完全独立的业务场景(登录成功/登录失败)耦合在同一个类中,代码可读性差,后续维护成本极高

密封类实现方案

密封类可以限定响应只有成功、错误两种类型,每个类型持有自己独有的字段,天然适配异构响应的场景,示例代码如下:

// 密封类根类,限定认证响应只有两种类型
sealed class AuthResponse

// 登录成功响应实体
data class AuthSuccess(
    val access_token: String,
    val token_type: String
) : AuthResponse()

// 错误详情条目实体
data class ErrorDetail(
    val loc: List<String>,
    val msg: String,
    val type: String
)

// 登录失败响应实体
data class AuthError(
    val detail: List<ErrorDetail>
) : AuthResponse()

后续处理响应时直接通过when表达式分支处理即可,编译器会自动校验是否覆盖所有分支,无需额外判空,逻辑清晰安全:

fun handleAuthResult(response: AuthResponse) {
    when(response) {
        is AuthSuccess -> {
            // 直接使用token走登录成功逻辑
            saveAccessToken(response.access_token)
            navigateToHome()
        }
        is AuthError -> {
            // 直接取错误信息提示用户
            val errorMsg = response.detail.firstOrNull()?.msg ?: "登录失败,请稍后重试"
            showToast(errorMsg)
        }
    }
}

如果使用Retrofit做网络请求,只需要自定义一个Converter适配器,根据HTTP状态码(比如200走成功解析逻辑、4xx走错误解析逻辑)将返回值解析为对应子类实例即可,无需手动处理字段兼容问题。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 12:45:05