發(fā)現(xiàn)問(wèn)題
在項(xiàng)目開發(fā)中發(fā)現(xiàn)割去,發(fā)起網(wǎng)絡(luò)請(qǐng)求是會(huì)一直顯示Loading未檩。但是我們?cè)趏khttp初始化的時(shí)候已經(jīng)設(shè)置的網(wǎng)絡(luò)請(qǐng)求超時(shí)時(shí)間為30s兰吟。為什么會(huì)出現(xiàn)這種情況 WTF!
解決問(wèn)題
通過(guò)斷點(diǎn)調(diào)試發(fā)現(xiàn)近她,在AsyTask中發(fā)起網(wǎng)絡(luò)請(qǐng)求的位置停住了漓柑。導(dǎo)致線程一直無(wú)法中斷湖蜕。通過(guò)一步一步斷點(diǎn)發(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");
}
原來(lái)一直在執(zhí)行while循環(huán),Okhttp在網(wǎng)絡(luò)請(qǐng)示出現(xiàn)錯(cuò)誤時(shí)會(huì)重新發(fā)送請(qǐng)求昭抒,最終會(huì)不斷執(zhí)行
catch (IOException var13) {
if(!this.recover(var13, false, request)) {
throw var13;
}
releaseConnection = false;
continue;
}
可以看到這個(gè)方法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初始化的時(shí)候添加如下代碼即可
sClient = builder.retryOnConnectionFailure(false).build();
更新
該問(wèn)題 在3.4.2版本已處理
https://github.com/square/okhttp/issues/2756