很久之前看過
OkHttp
的源碼盗忱,但當(dāng)時(shí)沒有做總結(jié),今天突然想在腦海中過一遍OkHttp
內(nèi)部的執(zhí)行流程時(shí)并齐,發(fā)現(xiàn)一片混沌不知從何說起妖泄,于是今天重新過了一遍驹沿,參考了一篇從源碼角度進(jìn)行解析的文章并做了總結(jié),需要詳細(xì)源碼解讀的可以去看看這篇文章蹈胡,這里只做總結(jié)渊季,不重復(fù)造輪子,網(wǎng)上詳細(xì)解析OkHttp
的優(yōu)秀文章也很多罚渐。
先看一張流程圖(來自這篇文章),另外推薦博主的另一篇Retrofit解讀:
整體流程:
整個(gè)流程是却汉,通過
OkHttpClient
的newCall()
將構(gòu)建的Request
轉(zhuǎn)換為Call
,Call
內(nèi)部調(diào)用RealCall
荷并,然后在RealCall
中進(jìn)行異步或同步任務(wù)合砂,最后通過一系列的攔截器interceptor
發(fā)出網(wǎng)絡(luò)請(qǐng)求和得到返回的response
1 具體執(zhí)行流程:
整個(gè)請(qǐng)求流程是從RealCall開始的:
1.1 如果是同步請(qǐng)求( execute()
):
則會(huì)調(diào)用
dispatcher
的executed()
方法將請(qǐng)求任務(wù)加到同步請(qǐng)求運(yùn)行隊(duì)列中(即runningSyncCalls.add(call);
)然后調(diào)用getResponseWithInterceptorChain()
,該方法中通過執(zhí)行一系列的攔截器完成整個(gè)網(wǎng)絡(luò)的請(qǐng)求任務(wù)源织,最后會(huì)調(diào)用dispatcher
的finished()
方法告知我們執(zhí)行完畢了
1.2 如果是異步請(qǐng)求(enqueue()
):
主要用到了調(diào)度器
Dispatcher
既穆,我們調(diào)用enqueue()
方法后,在
RealCall
中會(huì)去調(diào)Dispatcher
的enqueue()
方法雀鹃,這個(gè)方法會(huì)判斷當(dāng)前的請(qǐng)求數(shù)量從而決定要將該請(qǐng)求添加到等待隊(duì)列還是添加到異步執(zhí)行隊(duì)列中利用線程池去執(zhí)行。執(zhí)行的時(shí)候調(diào)用的還是
getResponseWithInterceptorChain()
從而還是通過一系列的攔截器來完成網(wǎng)絡(luò)請(qǐng)求励两,不同的是這里是利用線程池來異步執(zhí)行任務(wù)黎茎。
2 這個(gè)Dispatcher攔截器是什么?:
Dispatcher
在同步請(qǐng)求中的作用只是用于告知我們執(zhí)行狀態(tài)当悔,例如開始執(zhí)行了(調(diào)用executed()
)以及運(yùn)行結(jié)束了(調(diào)用finished()
)
其主要作用是在異步執(zhí)行過程中傅瞻,
Dispatcher
的enqueue()
方法會(huì)判斷當(dāng)前的請(qǐng)求數(shù)量從而決定要將該請(qǐng)求添加到等待隊(duì)列還是添加到異步執(zhí)行隊(duì)列中利用線程池去執(zhí)行。任務(wù)的異步執(zhí)行真是在這里完成分配的盲憎。
3 攔截器又是什么嗅骄?
3.1 首先
RealCall中真正發(fā)起網(wǎng)絡(luò)請(qǐng)求以及解析返回結(jié)果的,是getResponseWithInterceptorChain() 饼疙,這個(gè)方法中將一系列的攔截器例如 重定向攔截器溺森、轉(zhuǎn)換攔截器、緩存攔截器、連接攔截器等 添加到一個(gè)
ArrayList
后通過一系列的鏈?zhǔn)秸{(diào)用執(zhí)行各個(gè)攔截器;
3.2 具體的攔截器包括:
- 負(fù)責(zé)失敗重試以及重定向的 RetryAndFollowUpInterceptor屏积;
- 負(fù)責(zé)把用戶構(gòu)造的請(qǐng)求轉(zhuǎn)換為發(fā)送到服務(wù)器的請(qǐng)求医窿、把服務(wù)器返回的響應(yīng)轉(zhuǎn)換為用戶友好的響應(yīng)的 BridgeInterceptor
- 負(fù)責(zé)讀取緩存直接返回、更新緩存的 CacheInterceptor(判斷是要去獲取網(wǎng)絡(luò)的Response還是直接使用緩存)炊林;
- 負(fù)責(zé)和服務(wù)器建立連接的 ConnectInterceptor姥卢;
- 配置
OkHttpClient
時(shí)設(shè)置的 networkInterceptors;- 負(fù)責(zé)向服務(wù)器發(fā)送請(qǐng)求數(shù)據(jù)渣聚、從服務(wù)器讀取響應(yīng)數(shù)據(jù)的 CallServerInterceptor独榴。
3.3 總的來說
攔截器是將請(qǐng)求一層一層向下傳,直到有一層能夠得到
Response
就停止并將Response
向上面的攔截器傳遞奕枝,然后各個(gè)攔截器會(huì)對(duì)Response
進(jìn)行一些處理最后傳到RealCall
類中返回
Interceptor的設(shè)計(jì)體現(xiàn)了設(shè)計(jì)模式中的單一職責(zé)原則
Interceptor 的設(shè)計(jì)是一種分層的思想棺榔,每個(gè) Interceptor 就是一層。分層簡(jiǎn)化了每一層的邏輯倍权,每層只需要關(guān)注自己的責(zé)任掷豺,而各層之間通過約定的接口/協(xié)議進(jìn)行合作(面向接口編程思想),共同完成復(fù)雜的任務(wù)薄声。