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

Retrofit无网络或返回空时崩溃:OkHttp拦截器空指针异常

解决OkHttp拦截器返回Null导致的空指针崩溃问题

从你提供的崩溃日志来看,直接原因是你的自定义OkHttp拦截器(RestClient$1@301dd345)在某些场景下返回了null——而OkHttp的RealInterceptorChain.proceed()方法要求所有拦截器必须返回一个非空的Response对象,哪怕是错误状态的响应,返回null会直接触发NullPointerException。

问题场景分析

你提到的无网络连接或接口返回空值时崩溃,刚好对应拦截器可能出现的两种错误分支:

  • 无网络时,拦截器可能直接返回了null,没有生成合法的错误响应
  • 接口返回空值时,拦截器没有对空响应做包装,导致最终传递给OkHttp链的Response为null

具体解决方案

1. 修复自定义拦截器的返回逻辑

找到RestClient中那个匿名拦截器的intercept()方法,确保所有分支都返回非空的Response:

@Override
public Response intercept(Chain chain) throws IOException {
    Request request = chain.request();
    
    // 1. 处理无网络场景
    if (!isNetworkAvailable()) {
        // 返回自定义的无网络错误响应
        return new Response.Builder()
                .request(request)
                .protocol(Protocol.HTTP_1_1)
                .code(503) // 推荐使用503(服务不可用)作为无网络状态码
                .message("No Network Connection")
                .body(ResponseBody.create(MediaType.parse("text/plain"), "No internet access"))
                .build();
    }
    
    // 2. 正常请求后处理空响应
    Response originalResponse = chain.proceed(request);
    if (originalResponse.body() == null) {
        // 将空body包装为合法的响应体(比如空JSON对象)
        return originalResponse.newBuilder()
                .body(ResponseBody.create(MediaType.parse("application/json"), "{}"))
                .build();
    }
    
    // 3. 正常返回响应
    return originalResponse;
}

注意:isNetworkAvailable()是你自己实现的网络状态检测方法,确保它能准确判断设备是否联网。

2. 上层逻辑增加防护

即使拦截器修复了,也建议在Retrofit的回调/协程处理中增加非空判断,避免上层逻辑出现额外崩溃:

  • 对于Callback模式:
call.enqueue(new Callback<YourResponseModel>() {
    @Override
    public void onResponse(Call<YourResponseModel> call, Response<YourResponseModel> response) {
        if (response.isSuccessful() && response.body() != null) {
            // 处理正常响应
        } else {
            // 处理错误/空响应
        }
    }

    @Override
    public void onFailure(Call<YourResponseModel> call, Throwable t) {
        // 处理请求失败(比如无网络已经被拦截器处理,这里可能是其他错误)
    }
});
  • 对于Coroutine模式:
viewModelScope.launch {
    try {
        val response = apiService.yourApiCall()
        response.body()?.let {
            // 处理非空响应
        } ?: run {
            // 处理空响应
        }
    } catch (e: Exception) {
        // 处理异常
    }
}

3. 排查其他可能的拦截器

如果你配置了多个OkHttp拦截器,逐一检查每个拦截器的intercept()方法,确保没有任何一个拦截器在异常分支返回null。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 09:58:34