发现问题
在项目开发中发现,发起网络请求是会一直显示Loading。但是我们在okhttp初始化的时候已经设置的网络请求超时时间为30s。为什么会出现这种情况 WTF!
解决问题
通过断点调试发现,在AsyTask中发起网络请求的位置停住了。导致线程一直无法中断。通过一步一步断点发现。
Code
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
this.streamAllocation = new StreamAllocation(this.client.connectionPool(), this.createAddress(request.url()));
int followUpCount = 0;
Response priorResponse = null;
//while循环
while(!this.canceled) {
Response response = null;
boolean releaseConnection = true;
try {
response = ((RealInterceptorChain)chain).proceed(request, this.streamAllocation, (HttpStream)null, (Connection)null);
releaseConnection = false;
} catch (RouteException var12) {
if(!this.recover(var12.getLastConnectException(), true, request)) {
throw var12.getLastConnectException();
}
releaseConnection = false;
continue;
} catch (IOException var13) {
if(!this.recover(var13, false, request)) {
throw var13;
}
releaseConnection = false;
continue;
} finally {
if(releaseConnection) {
this.streamAllocation.streamFailed((IOException)null);
this.streamAllocation.release();
}
}
if(priorResponse != null) {
response = response.newBuilder().priorResponse(priorResponse.newBuilder().body((ResponseBody)null).build()).build();
}
Request followUp = this.followUpRequest(response);
if(followUp == null) {
if(!this.forWebSocket) {
this.streamAllocation.release();
}
return response;
}
Util.closeQuietly(response.body());
++followUpCount;
if(followUpCount > 20) {
this.streamAllocation.release();
throw new ProtocolException("Too many follow-up requests: " + followUpCount);
}
if(followUp.body() instanceof UnrepeatableRequestBody) {
throw new HttpRetryException("Cannot retry streamed HTTP body", response.code());
}
if(!this.sameConnection(response, followUp.url())) {
this.streamAllocation.release();
this.streamAllocation = new StreamAllocation(this.client.connectionPool(), this.createAddress(followUp.url()));
} else if(this.streamAllocation.stream() != null) {
throw new IllegalStateException("Closing the body of " + response + " didn\'t close its backing stream. Bad interceptor?");
}
request = followUp;
priorResponse = response;
}
this.streamAllocation.release();
throw new IOException("Canceled");
}
原来一直在执行while循环,Okhttp在网络请示出现错误时会重新发送请求,最终会不断执行
catch (IOException var13) {
if(!this.recover(var13, false, request)) {
throw var13;
}
releaseConnection = false;
continue;
}
可以看到这个方法recover只要将他返回false就可以了
private boolean recover(IOException e, boolean routeException, Request userRequest) {
this.streamAllocation.streamFailed(e);
return !this.client.retryOnConnectionFailure()?false:(!routeException && userRequest.body() instanceof UnrepeatableRequestBody?false:(!this.isRecoverable(e, routeException)?false:this.streamAllocation.hasMoreRoutes()));
}
既然retryOnConnectionFailure返回false
终上所述我们只需在Okhttp初始化的时候添加如下代码即可
sClient = builder.retryOnConnectionFailure(false).build();
更新
该问题 在3.4.2版本已处理
https://github.com/square/okhttp/issues/2756