OKhtt原理以及異步執(zhí)行過程
? ? 先上圖,這是Okhttp官網(wǎng)文檔的一張OKhttp請求執(zhí)行流程和經(jīng)過的攔截器泼舱,并且服務(wù)器響應(yīng)的時(shí)候經(jīng)過的攔截器躁绸。
? ? ? ? 大家看這張圖的時(shí)候按照流程執(zhí)行裕循,這是okhttp的請求執(zhí)行過程,從應(yīng)用發(fā)出request净刮,到應(yīng)用收到response剥哑,期間經(jīng)歷了N個(gè)攔截器,可以看出Okhttp的攔截器在整個(gè)請求的過程中起到了重大作用,扮演者中要的角色庭瑰。
? ? 攔截器的作用:
官方文檔翻譯
Rewriting Requests
Interceptors can add, remove, or replace request headers. They can also transform the body of those requests that have one. For example, you can use an application interceptor to add request body compression if you're connecting to a webserver known to support it.
? ? ? ? ? ?攔截器可以對每一個(gè)請求頭中的信息進(jìn)行星持,添加,移除弹灭,或者替換督暂。如有請求中有請求體的話還可以對請求體里里面的內(nèi)容做轉(zhuǎn)換。比如穷吮,你可以給你的應(yīng)用增加一個(gè)”內(nèi)容壓縮的攔截器“逻翁,對請求體中的內(nèi)容進(jìn)行壓縮,前提是你請求的服務(wù)器能支持你這種壓縮后的請求內(nèi)容捡鱼,所以要實(shí)現(xiàn)類型功能請后端必須溝通好八回,比如前端采用什么樣的壓縮算法,后端接收到請求后,采用相同的算法解壓缠诅。不過一般來說我們都不會(huì)采用這種攔截器溶浴,因?yàn)閛khttp 默認(rèn)就支持GZIP壓縮
OKhttp3 核心
?Okhttp3 是一個(gè)高性能網(wǎng)絡(luò)請求框架,支持支持HTTPS/HTTP2/WebSocket 管引,其核心有一下幾點(diǎn):
????1士败、采用責(zé)任鏈方式的攔截器,實(shí)現(xiàn)分成處理網(wǎng)絡(luò)請求褥伴,讓用戶對網(wǎng)絡(luò)請求實(shí)現(xiàn)了更好的擴(kuò)展
????2谅将、GZIP處理降低了下載數(shù)據(jù)的大小
????3、支持http 緩存
????4重慢、采用線程池(thread pool)和連接池(socket pool)解決多并發(fā)問題饥臂,同時(shí)連接池采支持多路復(fù)用(http2才支持多路復(fù)用,單路復(fù)用指的是似踱,個(gè)socket 只有把一個(gè)請求發(fā)送完成后隅熙,才能繼續(xù)發(fā)送第二個(gè)請求,多路復(fù)用可以讓一個(gè)socket 同時(shí)發(fā)送多個(gè)請求的數(shù)據(jù)屯援,內(nèi)部會(huì)自動(dòng)維護(hù)順序)猛们,減少連接創(chuàng)建開銷
????5、底層采用 socket 和服務(wù)器進(jìn)行連接狞洋。
????6弯淘、采用okio 實(shí)現(xiàn)高效的io流讀寫
OkhttpCore(內(nèi)置5大核心攔截器)
上圖攔截器流程示意圖中,其中OkhttCore 包含了五大核心攔截器吉懊,它們承擔(dān)了整個(gè)網(wǎng)絡(luò)請求的全部工作庐橙。
1.RetryAndFollowUpInterceptor
RetryAndFollowUpInterceptor 的作用,看到該攔截器的名稱就知道借嗽,它就是一個(gè)負(fù)責(zé)失敗重連和重定向的攔截器态鳖。它是 Okhttp 內(nèi)置的第一個(gè)攔截器,通過 while (true) 的死循環(huán)來進(jìn)行對異常結(jié)果或者響應(yīng)結(jié)果判斷是否要進(jìn)行重新請求恶导。
2.BridgeInterceptor
BridgeInterceptor 為用戶構(gòu)建的一個(gè) Request 請求轉(zhuǎn)化為能夠進(jìn)行網(wǎng)絡(luò)訪問的請求浆竭,同時(shí)將網(wǎng)絡(luò)請求回來的響應(yīng) Response 轉(zhuǎn)化為用戶可用的 Response。比如惨寿,涉及的網(wǎng)絡(luò)文件的類型和網(wǎng)頁的編碼邦泄,返回的數(shù)據(jù)的解壓處理等等。
3.CacheInterceptor
CacheInterceptor 根據(jù) OkHttpClient 對象的配置以及緩存策略對請求值進(jìn)行緩存裂垦。
4.ConnectInterceptor
ConnectInterceptor 在 OKHTTP 底層是通過 SOCKET 的方式于服務(wù)端進(jìn)行連接的顺囊,并且在連接建立之后會(huì)通過 OKIO 獲取通向 server 端的輸入流 Source 和輸出流 Sink。
5.CallServerInterceptor
CallServerInterceptor 在 ConnectInterceptor 攔截器的功能就是負(fù)責(zé)與服務(wù)器建立 Socket 連接蕉拢,并且創(chuàng)建了一個(gè) HttpStream 它包括通向服務(wù)器的輸入流和輸出流特碳。而接下來的 CallServerInterceptor 攔截器的功能使用 HttpStream 與服務(wù)器進(jìn)行數(shù)據(jù)的讀寫操作的诚亚。
自定義攔截器
1.應(yīng)用攔截器 Application Interceptor
2.網(wǎng)絡(luò)攔截器 NetWork Interceptor
他們的異同:
相同點(diǎn)
1)都能對server返回的response進(jìn)行攔截
? ? ? 2)這兩種攔截器本質(zhì)上都是基于Interceptor接口,由開發(fā)者實(shí)現(xiàn)這個(gè)接口午乓,然后將自定義的Interceptor類的對象設(shè)置到okhttpClient對象中站宗,所以,本質(zhì)上沒什么不同益愈,都是Interceptor的實(shí)現(xiàn)類的對象份乒。
3)兩者都會(huì)被add到OkHttpClient內(nèi)的一個(gè)ArrayList中。當(dāng)請求執(zhí)行的時(shí)候腕唧,多個(gè)攔截器會(huì)依次執(zhí)行(list本身就是有序的)。
不同點(diǎn)
1)okhttpClient添加兩種攔截器的api不同瘾英。添加應(yīng)用攔截器的接口是addInterceptor()枣接,而添加網(wǎng)絡(luò)攔截器的接口是addNetworkInterceptor().
2)兩者負(fù)責(zé)的區(qū)域不同,從最上方圖中可以看出缺谴,應(yīng)用攔截器作用于okhttpCore到Application之間但惶,網(wǎng)絡(luò)攔截器作用于 network和okhttpCore之間
3)在某種特殊情況下(比如:訪問了一個(gè)url,結(jié)果這個(gè)url發(fā)生了重定向)湿蛔,網(wǎng)絡(luò)攔截器有可能被執(zhí)行多次膀曾,但是 不論任何情況,application只會(huì)被執(zhí)行一次阳啥。
? ? 核心源碼?
? 構(gòu)建完成Request的后通關(guān)newCall發(fā)送請求返回一個(gè)Call對象后執(zhí)行異步請求
進(jìn)到RealCall類中的異步方法? 看到最后一行代碼添谊,okhttpclient對象調(diào)用dispatcher方法返回一個(gè)dispatcher對象進(jìn)行調(diào)用dispatcher中的異步方法將call放入異步任務(wù)中并將匿名異步任務(wù)對象傳入道此方法中,? 這里的使用的鏈?zhǔn)骄幊?/p>
進(jìn)入到disparcher中找到enqueue方法
這里首先是將異步任務(wù)添加到了一個(gè)準(zhǔn)備任務(wù)隊(duì)列中察迟,
if判斷中是對正在執(zhí)行的任務(wù)隊(duì)列或者準(zhǔn)備執(zhí)行的任務(wù)隊(duì)列中找之前執(zhí)行的異步任務(wù) AsyncCall斩狱,首先去準(zhǔn)備任務(wù)隊(duì)列中去尋找,找不到了再去正在執(zhí)行的任務(wù)隊(duì)列中去找扎瓶,
找到之后去判斷是否為空所踊,不為空的話會(huì)將找的異步任務(wù)傳入ReakCall中賦值給本次異步任務(wù)(AtomicInteger 一個(gè)計(jì)數(shù)器,線程安全)概荷,這個(gè)后面會(huì)提到秕岛。
最后調(diào)用的promoteAndExecute()? 這個(gè)方法大家從字面意思上看大概也知道這就是準(zhǔn)備執(zhí)行了,
Dispatcher 的promoteAndExecute 方法: