一、写在前面 关于okhttp3的解析网上已经有非常多优秀的博文了,每每看完都觉得醍醐灌顶,豁然开朗。但等不了几天再回头看,还是跟当初一样陌生,究其根本原因,我们不过是在享受着别人的成果跟着别人的思路云阅读源码了一遍。okhttp从早期的Java版本到Kotlin版本一直不断优化升级,实现细节上也作出了调整。重读源码加上自身的思考能深刻地理解okhttp的实现原理。二、从基本使用说起项目中引入依赖,Github地址okhttpdependencies{。。。implementation(com。squareup。okhttp3:okhttp:4。9。3)}从一个简单的同步(execute)请求入手分析整体的加载流程:privatefunclientNetWork(){valrequest:RequestRequest。Builder()。url(https:www。baidu。com)。build()OkHttpClient()。newCall(request)。execute()} 从execute()开始,发现其实是一个接口中的方法(Call),这个很好理解根据官方的解释,Call其实是一个待执行的请求,并且这个请求所要的参数已经被准备好;当然既然是请求,那么它是可以被取消的。其次代表单个请求与响应流,因此不能够被再次执行。Acallisarequestthathasbeenpreparedforexecution。Acallcanbecanceled。Asthisobjectrepresentsasinglerequestresponsepair(stream),itcannotbeexecutedtwice。 Call接口具体的代码实现,重点关注同步执行方法execute()与异步请求enqueue():interfaceCall:Cloneable{funrequest():Request同步请求Throws(IOException::class)funexecute():Response起步请求funenqueue(responseCallback:Callback)funcancel()funisExecuted():BooleanfunisCanceled():BooleanfuninterfaceFactory{funnewCall(request:Request):Call}} Call作为接口,那么具体的实现细节则需要看它的实现类,RealCall作为Call的实现类,先找到对execute()的重写。RealCall是应用程序与网络之间的桥梁,看看具体有什么作用,首先分析同步请求execute()方法的实现:overridefunexecute():Response{check(executed。compareAndSet(false,true)){AlreadyExecuted}1timeout。enter()2callStart()3try{client。dispatcher。executed(this)4returngetResponseWithInterceptorChain()5}finally{client。dispatcher。finished(this)6}} 代码很少,逐步分析,首先对同步请求进行了检查判断请求是否已经被执行过了;而这里使用的是并发包下的原子类CAS乐观锁,这里使用CAS比较算法目的也是为提升效率。其次是超时时间的判断,这个比较简单。在看callStart()的具体实现。上代码:privatefuncallStart(){this。callStackTracePlatform。get()。getStackTraceForCloseable(response。body()。close())eventListener。callStart(this)} 看名称猜测应该是事件监听之类的,可能是包括一些信息的记录与打印。回到RealCall类中,看看这个eventListener的作用到底是什么: internalvaleventListener:EventListenerclient。eventListenerFactory。create(this) 继续向下可以知道这个EventListener是一个抽象类,而项目中其唯一实现类为LoggingEventListener,猜测还是有依据的,继续往下看:abstractclassEventListener{openfuncallStart(call:Call){}省略了其他的方法} 实现类LoggingEventListener中对此方法的具体实现:classLoggingEventListenerprivateconstructor(privatevallogger:HttpLoggingInterceptor。Logger):EventListener(){overridefuncallStart(call:Call){startNsSystem。nanoTime()logWithTime(callStart:{call。request()})}} 总结这个callStart()的作用,当同步请求或者异步请求被加到队列时,callStart()会被立即执行(在没有达到线程限制的情况下)记录请求开始的时间与请求的一些信息。如下:overridefuncallStart(call:Call){startNsSystem。nanoTime()logWithTime(callStart:{call。request()})}privatefunlogWithTime(message:String){valtimeMsTimeUnit。NANOSECONDS。toMillis(System。nanoTime()startNs)logger。log(〔timeMsms〕message)} 代卖第四段4client。dispatcher。executed(this),看样子是在这里开启执行的,可实际真是如此嘛?回到OkHttpClient类中,看看这个分发器dispatcher到底是什么。get:JvmName(dispatcher)valdispatcher:Dispatcherbuilder。dispatcher 具体实现类Dispatcher代码(保留重要代码):classDispatcherconstructor(){Readyasynccallsintheordertheyllberun。privatevalreadyAsyncCallsArrayDeque()Runningasynchronouscalls。Includescanceledcallsthathaventfinishedyet。privatevalrunningAsyncCallsArrayDeque()Runningsynchronouscalls。Includescanceledcallsthathaventfinishedyet。privatevalrunningSyncCallsArrayDequeRealCall()constructor(executorService:ExecutorService):this(){this。executorServiceOrNullexecutorService}get:SynchronizedvarmaxRequests64set(maxRequests){require(maxRequests1){max1:maxRequests}synchronized(this){fieldmaxRequests}promoteAndExecute()}get:SynchronizedvarmaxRequestsPerHost5set(maxRequestsPerHost){require(maxRequestsPerHost1){max1:maxRequestsPerHost}synchronized(this){fieldmaxRequestsPerHost}promoteAndExecute()}异步请求internalfunenqueue(call:AsyncCall){synchronized(this){readyAsyncCalls。add(call)MutatetheAsyncCallsothatitsharestheAtomicIntegerofanexistingrunningcalltothesamehost。if(!call。call。forWebSocket){valexistingCallfindExistingCallWithHost(call。host)if(existingCall!null)call。reuseCallsPerHostFrom(existingCall)}}promoteAndExecute()}同步请求Usedby〔Call。execute〕tosignalitisinflight。Synchronizedinternalfunexecuted(call:RealCall){runningSyncCalls。add(call)}privatefunpromoteAndExecute():Boolean{this。assertThreadDoesntHoldLock()valexecutableCallsmutableListOf()valisRunning:Booleansynchronized(this){valireadyAsyncCalls。iterator()while(i。hasNext()){valasyncCalli。next()Maxcapacity。if(runningAsyncCalls。sizethis。maxRequests)breakHostmaxcapacity。if(asyncCall。callsPerHost。get()this。maxRequestsPerHost)continuei。remove()asyncCall。callsPerHost。incrementAndGet()executableCalls。add(asyncCall)runningAsyncCalls。add(asyncCall)}isRunningrunningCallsCount()0}for(iin0untilexecutableCalls。size){valasyncCallexecutableCalls〔i〕asyncCall。executeOn(executorService)}returnisRunning}} 根据注释的信息可以知道,Dispatcher是处理异步请求的执行的策略,当然开发可以实现自己的策略。Policyonwhenasyncrequestsareexecuted。EachdispatcherusesanExecutorServicetoruncallsinternally。Ifyousupplyyourownexecutor,itshouldbeabletoruntheconfiguredmaximumnumberofcallsconcurrently。 知道了Dispatcher的作用,再回到client。dispatcher。executed(this),也即:Usedby〔Call。execute〕tosignalitisinflight。Synchronizedinternalfunexecuted(call:RealCall){runningSyncCalls。add(call)} 结合execute()与Dispatcher分析Dispatcher主要是对异步请求的调度作用,内部实现了线程池,对请求进行分发执行。包含三个双端队列分别为等待的异步队列readyAsyncCalls、执行中的队列runningAsyncCalls、执行中的同步队列runningSyncCalls。这里使用ArrayDeque,为什么不使用LinkedList有兴趣的可以思考一下。当请求为同步请求时,内部执行execute()将RealCall添加到runningSyncCalls队列中。 到这里请求其实还没有真正的执行,只是在做一些前期的工作,回到Call接口中看看对方法同步请求方法execute()的说明:同步请求可以立即执行,阻塞直到返回正确的结果,或者报错结束。Invokestherequestimmediately,andblocksuntiltheresponsecanbeprocessedorisinerror。 到4步执行后,returngetResponseWithInterceptorChain()5这个方法才是请求一步步推进的核心。也是okhttp网络请求责任链的核心模块。三、链的开启getResponseWithInterceptorChain()getResponseWithInterceptorChain()具体实现Throws(IOException::class)internalfungetResponseWithInterceptorChain():Response{Buildafullstackofinterceptors。valinterceptorsmutableListOfInterceptor()interceptorsclient。interceptorsinterceptorsRetryAndFollowUpInterceptor(client)interceptorsBridgeInterceptor(client。cookieJar)interceptorsCacheInterceptor(client。cache)interceptorsConnectInterceptorif(!forWebSocket){interceptorsclient。networkInterceptors}interceptorsCallServerInterceptor(forWebSocket)valchainRealInterceptorChain(callthis,interceptorsinterceptors,index0,exchangenull,requestoriginalRequest,connectTimeoutMillisclient。connectTimeoutMillis,readTimeoutMillisclient。readTimeoutMillis,writeTimeoutMillisclient。writeTimeoutMillis)varcalledNoMoreExchangesfalsetry{valresponsechain。proceed(originalRequest)if(isCanceled()){response。closeQuietly()throwIOException(Canceled)}returnresponse}catch(e:IOException){calledNoMoreExchangestruethrownoMoreExchanges(e)asThrowable}finally{if(!calledNoMoreExchanges){noMoreExchanges(null)}}} 分析getResponseWithInterceptorChain()方法之前有必要看看OkHttpClient的构造参数,使用的Builder模式,参数很多,可配置化的东西很多,精简一下主要关注几个参数:classBuilderconstructor(){异步请求任务调度器internalvardispatcher:DispatcherDispatcher()链接池internalvarconnectionPool:ConnectionPoolConnectionPool()自定义拦截器internalvalinterceptors:MutableListInterceptormutableListOf()自定义网络拦截器internalvalnetworkInterceptors:MutableListInterceptormutableListOf()缓存internalvarcache:Cache?null代理internalvarproxy:Proxy?null链接协议internalvarprotocols:ListProtocolDEFAULTPROTOCOLS。。。。。。。}添加自定义拦截器的方法funaddInterceptor(interceptor:Interceptor)apply{interceptorsinterceptor}添加自定义网络拦截器的方法funaddNetworkInterceptor(interceptor:Interceptor)apply{networkInterceptorsinterceptor} 到这里有个疑问,这个添加自定义拦截器与添加自定义网络拦截器有什么区别呢?方法看上去是差不多的,查看官方的说明可以发现一些细节。文档中解释了ApplicationInterceptor与NetworkInterceptors的细微差别。先回到RealCall中查看getResponseWithInterceptorChain()是如何对拦截器结合组装的:internalfungetResponseWithInterceptorChain():Response{Buildafullstackofinterceptors。valinterceptorsmutableListOfInterceptor()interceptorsclient。interceptors1interceptorsRetryAndFollowUpInterceptor(client)interceptorsBridgeInterceptor(client。cookieJar)interceptorsCacheInterceptor(client。cache)interceptorsConnectInterceptorif(!forWebSocket){interceptorsclient。networkInterceptors2}interceptorsCallServerInterceptor(forWebSocket)} 看1与2分别对应添加的自定义拦截器与自定义网络拦截器的位置,自定义拦截器是拦截器链的链头,而自定义网络拦截器在ConnectInterceptor拦截器与CallServerInterceptor拦截器之间被添加。总结一下:自定义拦截器在整个拦截器链的头部,做一些请求的之前的准备工作,包括一些Log的信息打印,如LoggingInterceptor。自定义网络拦截器添加在ConnectInterceptor与CallServerInterceptor之间,可以执行两次,并且获得的信息更多,包括原网址的信息和重定向后网址的信息。Applicationinterceptors Don’tneedtoworryaboutintermediateresponseslikeredirectsandretries。 Arealwaysinvokedonce,eveniftheHTTPresponseisservedfromthecache。 Observetheapplication’soriginalintent。UnconcernedwithOkHttpinjectedheaderslikeIfNoneMatch。 PermittedtoshortcircuitandnotcallChain。proceed()。 PermittedtoretryandmakemultiplecallstoChain。proceed()。 CanadjustCalltimeoutsusingwithConnectTimeout,withReadTimeout,withWriteTimeout。NetworkInterceptors Abletooperateonintermediateresponseslikeredirectsandretries。 Notinvokedforcachedresponsesthatshortcircuitthenetwork。 Observethedatajustasitwillbetransmittedoverthenetwork。 AccesstotheConnectionthatcarriestherequest。 综上可以得出整个链的顺序结构,如果都包含自定义拦截器与自定义网络拦截器,则为自定义拦截器RetryAndFollowUpInterceptorBridgeInterceptorCacheInterceptorConnectInterceptor自定义网络拦截器CallServerInterceptor;那么链是如何按照顺序依次执行的呢?okhttp在这里设计比较精妙,在构造RealInterceptorChain对象时带入index信息,这个index记录的就是单个拦截器链的位置信息,而RealInterceptorChain。proceed(request:Request)通过index自增一步步执行责任链一直到链尾。valchainRealInterceptorChain(callthis,interceptorsinterceptors,记录了拦截器对应的index通过对index0,exchangenull,requestoriginalRequest,connectTimeoutMillisclient。connectTimeoutMillis,readTimeoutMillisclient。readTimeoutMillis,writeTimeoutMillisclient。writeTimeoutMillis)valresponsechain。proceed(originalRequest)四、proceed链的推进RealInterceptorChain中方法proceed()方法的具体实现Throws(IOException::class)overridefunproceed(request:Request):Response{check(indexinterceptors。size)callsif(exchange!null){check(exchange。finder。sameHostAndPort(request。url)){networkinterceptor{interceptors〔index1〕}mustretainthesamehostandport}check(calls1){networkinterceptor{interceptors〔index1〕}mustcallproceed()exactlyonce}}Callthenextinterceptorinthechain。valnextcopy(indexindex1,requestrequest)valinterceptorinterceptors〔index〕Suppress(USELESSELVIS)valresponseinterceptor。intercept(next)?:throwNullPointerException(interceptorinterceptorreturnednull)。。。。。returnresponse} 简单的分析推进过程: 1。RealInterceptorChain的构造参数中携带了index的信息,index自增通过proceed方法不断执行。 2。拦截器统一实现Interceptor接口,接口中funproceed(request:Request):Response保证了链式链接。当然拦截器的顺序是按照一定的规则排列的,逐个分析。五、RetryAndFollowUpInterceptor重试与重定向companionobject{privateconstvalMAXFOLLOWUPS20}overridefunintercept(chain:Interceptor。Chain):Response{valrealChainchainasRealInterceptorChainvarrequestchain。requestvalcallrealChain。callvarfollowUpCount0varpriorResponse:Response?nullvarnewExchangeFindertruevarrecoveredFailureslistOfIOException()while(true){。。。。try{responserealChain。proceed(request)newExchangeFindertrue}}。。。。} 1。重试拦截器规定默认的重试次数为20次 2。以responserealChain。proceed(request)为分界点,包括其他的拦截器,在责任链传递之前所做的工作都是前序工作,然后将request下发到下一个拦截器。 3。responserealChain。proceed(request)后的代码逻辑为后续工作,即拿到上个拦截器的response结果,有点递归的意思,按照责任链的执行一直到最后一个拦截器获得的结果依次上抛每个拦截器处理这个response完成一些后序工作。 4。当然并不是每个请求都会走完整个链,如CacheInterceptor当开启了缓存(存在缓存)拿到了缓存的response那么之后的拦截器就不会在继续传递。六、BridgeInterceptoroverridefunintercept(chain:Interceptor。Chain):Response{valuserRequestchain。request()valrequestBuilderuserRequest。newBuilder()valbodyuserRequest。bodyif(body!null){valcontentTypebody。contentType()if(contentType!null){requestBuilder。header(ContentType,contentType。toString())}valcontentLengthbody。contentLength()if(contentLength!1L){requestBuilder。header(ContentLength,contentLength。toString())requestBuilder。removeHeader(TransferEncoding)}else{requestBuilder。header(TransferEncoding,chunked)requestBuilder。removeHeader(ContentLength)}}。。。。。分界点,上部分为前序操作valnetworkResponsechain。proceed(requestBuilder。build())下部分代码为拿到response的后序操作cookieJar。receiveHeaders(userRequest。url,networkResponse。headers)} 1。桥接拦截器主要对请求的Hader的信息的补充,包括内容长度等。 2。传递请求到下一个链,等待返回的response信息。 3。后序的操作包括Cookie、gzip压缩信息,UserAgent等信息的补充。七、CacheInterceptoroverridefunintercept(chain:Interceptor。Chain):Response{valcallchain。call()valcacheCandidatecache?。get(chain。request())valnowSystem。currentTimeMillis()valstrategyCacheStrategy。Factory(now,chain。request(),cacheCandidate)。compute()valnetworkRequeststrategy。networkRequestvalcacheResponsestrategy。cacheResponse。。。。。。varnetworkResponse:Response?nulltry{networkResponsechain。proceed(networkRequest)}finally{IfwerecrashingonIOorotherwise,dontleakthecachebody。if(networkResponsenullcacheCandidate!null){cacheCandidate。body?。closeQuietly()}}。。。。。}OkHttpClient的默认构造中是没有开启缓存的;internalvarcache:Cache?null,需要手动添加,但是有默认实现,基于最近最少使用算法实现的DiskLruCache磁盘缓存:privatevalclient:OkHttpClientOkHttpClient。Builder()。cache(Cache(directoryFile(application。cacheDir,httpcache),0。05worthofphonestoragein2020maxSize50L1024L1024L50MiB))。build() 1。缓存拦截器默认没有被开启,需要在调用时指定缓存的目录,内部基于DiskLruCache实现了磁盘缓存。 2。当缓存开启,且命中缓存,那么链的调用不会再继续向下传递(此时已经拿到了response)直接进行后序的操作。 3。如果未命中,则会继续传递到下一个链也即是ConnectInterceptor。八、ConnectInterceptorOpensaconnectiontothetargetserverandproceedstothenextinterceptor。Thenetworkmightbeusedforthereturnedresponse,ortovalidateacachedresponsewithaconditionalGET。objectConnectInterceptor:Interceptor{Throws(IOException::class)overridefunintercept(chain:Interceptor。Chain):Response{valrealChainchainasRealInterceptorChainvalexchangerealChain。call。initExchange(chain)valconnectedChainrealChain。copy(exchangeexchange)returnconnectedChain。proceed(realChain。request)}}ConnectInterceptor的代码量很少主要作用很清晰。 1。建立与目标的服务器的TCP或者TCPTLS的链接。 2。与之前的拦截器不同,前面的拦截器的前序操作基于调用方法realChain。proceed()之前,但是ConnectInterceptor没有后序操作,下发到下一个拦截器。九、CallServerInterceptorThrows(IOException::class)overridefunintercept(chain:Interceptor。Chain):Response{valrealChainchainasRealInterceptorChainvalexchangerealChain。exchange!!valrequestrealChain。requestvalrequestBodyrequest。bodyvalsentRequestMillisSystem。currentTimeMillis()exchange。writeRequestHeaders(request)varinvokeStartEventtruevarresponseBuilder:Response。Builder?nullif(HttpMethod。permitsRequestBody(request。method)requestBody!null){if(100continue。equals(request。header(Expect),ignoreCasetrue)){exchange。flushRequest()responseBuilderexchange。readResponseHeaders(expectContinuetrue)exchange。responseHeadersStart()invokeStartEventfalse}if(responseBuildernull){if(requestBody。isDuplex()){exchange。flushRequest()valbufferedRequestBodyexchange。createRequestBody(request,true)。buffer()requestBody。writeTo(bufferedRequestBody)}else{valbufferedRequestBodyexchange。createRequestBody(request,false)。buffer()requestBody。writeTo(bufferedRequestBody)bufferedRequestBody。close()}}else{exchange。noRequestBody()if(!exchange。connection。isMultiplexed){exchange。noNewExchangesOnConnection()}}}else{exchange。noRequestBody()}if(requestBodynull!requestBody。isDuplex()){exchange。finishRequest()}if(responseBuildernull){responseBuilderexchange。readResponseHeaders(expectContinuefalse)!!if(invokeStartEvent){exchange。responseHeadersStart()invokeStartEventfalse}}varresponseresponseBuilder。request(request)。handshake(exchange。connection。handshake())。sentRequestAtMillis(sentRequestMillis)。receivedResponseAtMillis(System。currentTimeMillis())。build()varcoderesponse。codeif(code100){responseBuilderexchange。readResponseHeaders(expectContinuefalse)!!if(invokeStartEvent){exchange。responseHeadersStart()}responseresponseBuilder。request(request)。handshake(exchange。connection。handshake())。sentRequestAtMillis(sentRequestMillis)。receivedResponseAtMillis(System。currentTimeMillis())。build()coderesponse。code}exchange。responseHeadersEnd(response)responseif(forWebSocketcode101){response。newBuilder()。body(EMPTYRESPONSE)。build()}else{response。newBuilder()。body(exchange。openResponseBody(response))。build()}if(close。equals(response。request。header(Connection),ignoreCasetrue)close。equals(response。header(Connection),ignoreCasetrue)){exchange。noNewExchangesOnConnection()}if((code204code205)response。body?。contentLength()?:1L0L){throwProtocolException(HTTPcodehadnonzeroContentLength:{response。body?。contentLength()})}returnresponse}}CallServerInterceptor是整个责任链的尾链: 1。实质上是请求与IO操作,将请求的数据写入到Socket中。 2。从Socket读取响应的数据TCPTCPTLS对应的端口,对于IO操作基于的是okio,而okhttp的高效请求同样离不开okio的支持。 3。拿到数据reponse返回到之前包含有后序操作的拦截器,但ConnectInterceptor除外,ConnectInterceptor是没有后续操作的。 整个拦截器流程图如下: 十、ReaclCall。execute()回头看同步请求的方法:overridefunexecute():Response{check(executed。compareAndSet(false,true)){AlreadyExecuted}timeout。enter()callStart()try{client。dispatcher。executed(this)returngetResponseWithInterceptorChain()}finally{client。dispatcher。finished(this)}}在Dispatcher中对于同步的请求仅仅只是将,RealCall的实例添加到runningSyncCalls。add(call)执行中的队列中。RealCall是Call的唯一实现类,而对于execute()方法的定义明确了,立即执行并阻塞直到response结果的返回或者error信息打断阻塞。经过getResponseWithInterceptorChain()的调用,链的推进此时已经拿到结果,那么后序的操作是什么呢?先看一个Java基础try{}finally{}结构,以及dispatcher。finished(call:RealCall)。try{client。dispatcher。executed(this)returngetResponseWithInterceptorChain()}finally{client。dispatcher。finished(this)}Usedby〔Call。execute〕tosignalcompletion。internalfunfinished(call:RealCall){finished(runningSyncCalls,call)} 1。排除极端的情况,System。exit()或者其他,finally块必然执行,不论发生异常与否,也不论在finally之前是否有return。 2。不管在try块中是否包含return,finally块总是在return之前执行。 3。如果finally块中有return,那么try块和catch块中的return就没有执行机会了。 Tip:第二条的结论很重要,回到execute()方法,dispatcher。finished(this)在结果response结果返回之前执行,看finished()具体实现。Usedby〔Call。execute〕tosignalcompletion。internalfunfinished(call:RealCall){finished(runningSyncCalls,call)}privatefunTfinished(calls:DequeT,call:T){validleCallback:Runnable?synchronized(this){1if(!calls。remove(call))throwAssertionError(Callwasntinflight!)idleCallbackthis。idleCallback}2valisRunningpromoteAndExecute()if(!isRunningidleCallback!null){idleCallback。run()}}privatefunpromoteAndExecute():Boolean{this。assertThreadDoesntHoldLock()valexecutableCallsmutableListOf()valisRunning:Booleansynchronized(this){3valireadyAsyncCalls。iterator()while(i。hasNext()){valasyncCalli。next()Maxcapacity。if(runningAsyncCalls。sizethis。maxRequests)breakHostmaxcapacity。if(asyncCall。callsPerHost。get()this。maxRequestsPerHost)continuei。remove()asyncCall。callsPerHost。incrementAndGet()executableCalls。add(asyncCall)runningAsyncCalls。add(asyncCall)}4isRunningrunningCallsCount()0}for(iin0untilexecutableCalls。size){valasyncCallexecutableCalls〔i〕asyncCall。executeOn(executorService)}5returnisRunning}SynchronizedfunrunningCallsCount():IntrunningAsyncCalls。sizerunningSyncCalls。size 1。1方法一,calls。remove(call)返回为true,也即是这个同步请求被从runningSyncCalls中移除释放;所以idleCallback为空。 2。3很显然asyncCall的结果为空,没有异步请求,在看4具体实现,runningSyncCalls的size为1。则isRunning的结果为true。idleCallback。run()不会被执行,并且idleCallback其实也是为空。至此,开始的例子所构建的同步请求就被执行完毕了,阻塞拿到了结果回调,用于页面展示或者其他操作。梳理整个流程如下: 1。从OkHttpClient()。newCall(request)。execute()开启同步请求任务。 2。得到的RealCall对象作为Call的唯一实现类,其中同步方法execute()是阻塞的,调用到会立即执行阻塞到有结果返回,或者发生错误error被打断阻塞。 3。RealCall中同步execute()请求方法被执行,而此时OkHttpClient实例中的异步任务分发器Dispatcher会将请求的实例RealCall添加到双端队列runningSyncCalls中去。 4。通过RealCall中的方法getResponseWithInterceptorChain()开启请求拦截器的责任链,将请求逐一下发,通过持有index并自增操作,其次除ConnectInterceptor与链尾CallServerInterceptor其余默认拦截器均有以chain。proceed(request)为分界点的前序与后序操作,拿到response后依次处理后序操作。 5。最终返回结果response之前,对进行中的同步任务做了移除队列的操作也即finally中client。dispatcher。finished(this)方法,最终得到的结果response返回到客户端,至此整个同步请求流程就结束了。十一、异步请求的处理enqueue()异步请求的大致流程与同步请求是差不多的,但是多了一个从等待队列到执行队列转化的一个过程。internalfunenqueue(call:AsyncCall){synchronized(this){1readyAsyncCalls。add(call)MutatetheAsyncCallsothatitsharestheAtomicIntegerofanexistingrunningcalltothesamehost。if(!call。call。forWebSocket){valexistingCallfindExistingCallWithHost(call。host)if(existingCall!null)call。reuseCallsPerHostFrom(existingCall)}}2promoteAndExecute()}privatefunpromoteAndExecute():Boolean{this。assertThreadDoesntHoldLock()valexecutableCallsmutableListOf()valisRunning:Booleansynchronized(this){valireadyAsyncCalls。iterator()while(i。hasNext()){3valasyncCalli。next()Maxcapacity。if(runningAsyncCalls。sizethis。maxRequests)breakHostmaxcapacity。if(asyncCall。callsPerHost。get()this。maxRequestsPerHost)continue4i。remove()asyncCall。callsPerHost。incrementAndGet()executableCalls。add(asyncCall)5runningAsyncCalls。add(asyncCall)}isRunningrunningCallsCount()0}for(iin0untilexecutableCalls。size){valasyncCallexecutableCalls〔i〕asyncCall。executeOn(executorService)}returnisRunning}1方法中将异步请求任务加入到readyAsyncCalls等待队列之中,2开启执行任务(当然Dispatcher维护了线程池来处理这些请求)。执行方法promoteAndExecute()中3将异步任务从等待队列readyAsyncCalls中取出并移除操作,5则添加到执行中的异步任务队列runningAsyncCalls,如此直到所有请求全部执行完毕。十二、小结这里仅仅是对大概的流程简单的作出了分析,忽略了一些其他的实现细节,像请求缓存池、请求的协议。包括本地缓存DiskLruCache的实现细节,以及异步请求的一些阀值的判断处理。在精力允许的情况下还应该仔细研究一番,毕竟从Java到现在的Kotlin版本okhttp经历了很多的迭代也更加成熟,当然网络请求这块okhttp的地位还是无法撼动的。十三、文档 Github Square