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
相关产品推荐
相关产品推荐

