从源码RetryAndFollowUpInterceptor#intercept方法说起
因为是失败从连,所以我们要看cacth相关部分的代码,代码如下:
① catch (RouteException e) { // The attempt to connect via a route failed. The request will not have been sent. 即连接网络超时 if (!recover(e.getLastConnectException(), true, request)) throw e.getLastConnectException(); releaseConnection = false; continue; }
recover(e.getLastConnectException(), true, request)
,接下来分析
recover(e.getLastConnectException(), true, request)
② /** * Report and attempt to recover from a failure to communicate with a server. Returns true if * {@code e} is recoverable, or false if the failure is permanent. Requests with a body can only * be recovered if the body is buffered. */ private boolean recover(IOException e, boolean routeException, Request userRequest) { streamAllocation.streamFailed(e); // The application layer has forbidden retries.OkHttp的retryOnConnectionFailure默认值是true if (!client.retryOnConnectionFailure()) return false; // We can't send the request body again.即超时了 if (!routeException && userRequest.body() instanceof UnrepeatableRequestBody) return false; // This exception is fatal. if (!isRecoverable(e, routeException)) return false; // No more routes to attempt. if (!streamAllocation.hasMoreRoutes()) return false; // For failure recovery, use the same route selector with a new connection. return true; }
根据调用者recover(e.getLastConnectException(), true, request)
request
传递的值为true
1、如果client.retryOnConnectionFailure没有配置过那么默认值是true,就会走if (!isRecoverable(e, routeException))分支,接着分析isRecoverable方法
③ private boolean isRecoverable(IOException e, boolean routeException) { // If there was a protocol problem, don't recover. if (e instanceof ProtocolException) { return false; } // If there was an interruption don't recover, but if there was a timeout connecting to a route // we should try the next route (if there is one). if (e instanceof InterruptedIOException) { return e instanceof SocketTimeoutException && routeException; } // Look for known client-side or negotiation errors that are unlikely to be fixed by trying // again with a different route. if (e instanceof SSLHandshakeException) { // If the problem was a CertificateException from the X509TrustManager, // do not retry. if (e.getCause() instanceof CertificateException) { return false; } } if (e instanceof SSLPeerUnverifiedException) { // e.g. a certificate pinning error. return false; } // An example of one we might want to retry with a different route is a problem connecting to a // proxy and would manifest as a standard IOException. Unless it is one we know we should not // retry, we return true and try a new route. return true; }
根据分析最终返回了return e instanceof SocketTimeoutException && routeException;该值为true,那么②将返回true,①将继续continue,进行了重连
2、如果client.retryOnConnectionFailure配置了false那么②会返回false,那么①的catch中if (!recover(e.getLastConnectException(), true, request))会返回true然后紧接着会抛出异常,程序并不进行二次重连
因此:如果不设置retryOnConnectionFailure那么Okhttp会自动重连,会导致网络不好的情况下怀疑自己设置的超时时间没有其作用,设置该值后转包分析确实没有进行了重连,由于当时没有保存截图此次就不贴图了。
限于水平有限,不知其中分析的是否正确,还望指正。Okhttp3源码工程