發(fā)現(xiàn)問題
在項目開發(fā)中發(fā)現(xiàn),發(fā)起網(wǎng)絡請求是會一直顯示Loading。但是我們在okhttp初始化的時候已經(jīng)設置的網(wǎng)絡請求超時時間為30s。為什么會出現(xiàn)這種情況 WTF!
解決問題
通過斷點調(diào)試發(fā)現(xiàn),在AsyTask中發(fā)起網(wǎng)絡請求的位置停住了。導致線程一直無法中斷。通過一步一步斷點發(fā)現(xiàn)。
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循環(huán)
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");
}
原來一直在執(zhí)行while循環(huán),Okhttp在網(wǎng)絡請示出現(xiàn)錯誤時會重新發(fā)送請求,最終會不斷執(zhí)行
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