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

如何在Retrofit与Kotlin中获取错误消息的响应体?

问题分析与解决方案

你当前的核心问题在于:外层的try-catch完全起不到作用——因为enqueue是异步调用,它仅负责发起请求,不会将请求过程中的异常抛出到当前线程的try块中,真正的错误分支要么是onResponse里的非成功响应,要么是onFailure里的网络/请求异常。

下面是改进后的代码,能完整获取服务器返回的具体错误信息:

api.uploadImage(imgId, requestBody).enqueue(object : Callback<Void> {
    override fun onResponse(call: Call<Void>, response: Response<Void>) {
        if (response.isSuccessful) {
            // 处理请求成功逻辑
        } else {
            // 获取非2xx响应的错误体
            response.errorBody()?.let { errorBody ->
                // 注意:errorBody.string()只能调用一次,流会被消耗
                val errorDetail = errorBody.string()
                Log.i("tag", "上传失败,错误详情: $errorDetail")
                
                // 如果服务器返回JSON格式错误信息,可解析为自定义模型
                // 示例:val errorModel = Gson().fromJson(errorDetail, ErrorModel::class.java)
            } ?: run {
                Log.i("tag", "上传失败,无可用错误信息")
            }
        }
    }

    override fun onFailure(call: Call<Void>, t: Throwable) {
        // 处理网络错误、超时、DNS解析失败等情况
        Log.i("tag", "上传失败: ${t.message}")
        
        // 进一步区分异常类型,获取更精准信息
        when(t) {
            is IOException -> Log.i("tag", "网络连接异常,请检查网络状态")
            is HttpException -> {
                val errorCode = t.code()
                val errorBody = t.response()?.errorBody()?.string()
                Log.i("tag", "HTTP错误码: $errorCode,错误详情: $errorBody")
            }
            else -> Log.i("tag", "未知错误: ${t.message}")
        }
    }
})

关键说明

  1. 移除无用的外层try-catch:异步请求的异常不会被这个try块捕获,完全是多余的。
  2. errorBody()的使用注意:它的string()方法只能调用一次,因为输入流会被读取后关闭,如果需要多次使用,要先把结果保存到变量中。
  3. 结构化错误解析:如果服务器返回的是JSON格式的错误(比如{"code":1001,"msg":"图片格式不支持"}),可以用Gson、Moshi等序列化库将字符串解析为自定义的错误模型类,方便直接提取具体字段。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 15:40:28