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

Retrofit中call.enqueue失效、response.body为空问题求助

解决Retrofit中call.enqueue无响应、onResponse不执行且response.body为null的问题

我来帮你一步步排查这个棘手的问题——这种静默无回调的情况,通常是请求链路里某个环节悄悄“卡壳”了,咱们从几个核心方向入手定位:

1. 先给请求加日志拦截器,看清真实的请求/响应细节

这是最关键的一步!没有日志的话,你根本不知道请求到底发没发出去、后端返回了什么。赶紧给OkHttpClient加上HttpLoggingInterceptor,设置BODY级别,这样能看到完整的请求头、请求体、响应状态码、响应体:

// 先添加依赖:implementation 'com.squareup.okhttp3:logging-interceptor:4.11.0'
val loggingInterceptor = HttpLoggingInterceptor().apply {
    level = HttpLoggingInterceptor.Level.BODY
}

val okHttpClient = OkHttpClient.Builder()
    .addInterceptor(loggingInterceptor)
    .build()

// 将配置好的client传入Retrofit
val retrofit = Retrofit.Builder()
    .baseUrl("你的接口基础URL")
    .client(okHttpClient)
    .addConverterFactory(GsonConverterFactory.create())
    .build()

跑起来看Logcat,重点关注这几个信息:

  • 请求头里的Authorization是不是正确带上了?有没有拼写错误(比如很多API要求格式是Bearer {token},别漏了Bearer 前缀)
  • 请求的URL是否正确,有没有拼错路径?
  • 后端返回的状态码是什么?如果是4xx/5xx,Retrofit会进入onResponse,但response.isSuccessful是false,这时候要调用response.errorBody()?.string()查看后端返回的错误信息,别只盯着response.body()
  • 如果连请求日志都看不到,说明请求根本没发出去,要查网络配置或Retrofit初始化问题

2. 检查请求头的格式是否符合后端要求

你提到只携带Authorization=token,很多后端接口要求这个头的格式是Authorization: Bearer <token>,如果少了Bearer 前缀,后端可能直接拒绝请求,甚至不返回任何内容。你可以在接口定义里这样写:

@GET("你的接口路径")
fun fetchData(@Header("Authorization") authHeader: String): Call<你的响应模型类>

调用的时候传"Bearer " + yourToken,如果后端确实不需要Bearer,那直接传token,但一定要和后端确认格式。

3. 验证响应模型和JSON结构是否完全匹配

如果日志显示后端返回了200和正确的JSON,但response.body()是null,大概率是Gson(或你用的转换器)解析失败了。检查你的响应模型类:

  • 字段名和JSON里的键是否完全匹配?比如JSON里是user_name,你的模型字段是userName,必须加@SerializedName("user_name")注解指定映射关系
  • 有没有遗漏必填字段?如果JSON里有非空字段,但模型里没定义,或者类型不匹配(比如JSON是字符串,模型里是Int),解析会失败,导致body为null
  • 可以直接打印response.raw().body()?.string()查看原始响应体,对比模型字段找差异

4. 排查基础配置问题

  • 检查AndroidManifest.xml里有没有加网络权限:<uses-permission android:name="android.permission.INTERNET"/>
  • 如果是Android 9及以上,用的是http请求,要在application标签里加android:usesCleartextTraffic="true"
  • 确认Retrofit的baseUrl有没有写错,是不是指向了正确的测试/生产环境服务器

5. 检查call对象的生命周期

如果你的call是在某个局部方法里创建的(比如Activity的按钮点击方法),方法执行完call对象被GC回收,也可能导致回调不触发。要确保call对象有全局引用,比如把它声明为Activity或ViewModel的成员变量:

// 在Activity中声明全局变量
private var fetchCall: Call<你的响应模型类>? = null

// 发起请求时赋值
fetchCall = apiService.fetchData(authHeader)
fetchCall?.enqueue(object : Callback<你的响应模型类> {
    // 实现回调逻辑
    override fun onResponse(call: Call<你的响应模型类>, response: Response<你的响应模型类>) {
        // 处理响应
    }

    override fun onFailure(call: Call<你的响应模型类>, t: Throwable) {
        // 处理失败
    }
})

// 记得在页面销毁时取消请求,避免内存泄漏
override fun onDestroy() {
    super.onDestroy()
    fetchCall?.cancel()
}

按照这个顺序排查,基本能定位到问题。优先看日志,这是最快找到根因的方法!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 08:39:45