/**
* Bridge between OkHttp's application and network layers. This class exposes high-level application
* layer primitives: connections, requests, responses, and streams.
*
* This class supports [asynchronous canceling][cancel]. This is intended to have the smallest
* blast radius possible. If an HTTP/2 stream is active, canceling will cancel that stream but not
* the other streams sharing its connection. But if the TLS handshake is still in progress then
* canceling may break the entire connection.
*/
/** Used by [Call.execute] to signal it is in-flight. */@Synchronizedinternalfunexecuted(call:RealCall){runningSyncCalls.add(call)}
再看
1
2
3
4
5
6
7
8
/** Ready async calls in the order they'll be run. */privatevalreadyAsyncCalls=ArrayDeque<AsyncCall>()/** Running asynchronous calls. Includes canceled calls that haven't finished yet. */privatevalrunningAsyncCalls=ArrayDeque<AsyncCall>()/** Running synchronous calls. Includes canceled calls that haven't finished yet. */privatevalrunningSyncCalls=ArrayDeque<RealCall>()
@Throws(IOException::class)internalfungetResponseWithInterceptorChain():Response{// Build a full stack of interceptors.valinterceptors=mutableListOf<Interceptor>()interceptors+=client.interceptorsinterceptors+=RetryAndFollowUpInterceptor(client)interceptors+=BridgeInterceptor(client.cookieJar)interceptors+=CacheInterceptor(client.cache)interceptors+=ConnectInterceptorif(!forWebSocket){interceptors+=client.networkInterceptors}interceptors+=CallServerInterceptor(forWebSocket)valchain=RealInterceptorChain(call=this,interceptors=interceptors,index=0,exchange=null,request=originalRequest,connectTimeoutMillis=client.connectTimeoutMillis,readTimeoutMillis=client.readTimeoutMillis,writeTimeoutMillis=client.writeTimeoutMillis)varcalledNoMoreExchanges=falsetry{valresponse=chain.proceed(originalRequest)if(isCanceled()){response.closeQuietly()throwIOException("Canceled")}returnresponse}catch(e:IOException){calledNoMoreExchanges=truethrownoMoreExchanges(e)asThrowable}finally{if(!calledNoMoreExchanges){noMoreExchanges(null)}}}
@Throws(IOException::class)overridefunproceed(request:Request):Response{check(index<interceptors.size)calls++if(exchange!=null){check(exchange.finder.sameHostAndPort(request.url)){"network interceptor ${interceptors[index - 1]} must retain the same host and port"}check(calls==1){"network interceptor ${interceptors[index - 1]} must call proceed() exactly once"}}// Call the next interceptor in the chain.valnext=copy(index=index+1,request=request)valinterceptor=interceptors[index]@Suppress("USELESS_ELVIS")valresponse=interceptor.intercept(next)?:throwNullPointerException("interceptor $interceptor returned null")if(exchange!=null){check(index+1>=interceptors.size||next.calls==1){"network interceptor $interceptor must call proceed() exactly once"}}check(response.body!=null){"interceptor $interceptor returned a response with no body"}returnresponse}