- 本文章所使用的 OkHttp 源碼版本:3.12.10
源碼解析
- 老套路拿霉,還是從 OkHttp 用法開始入手這塊的源碼
- 這個(gè)方法看起來有點(diǎn)可疑吟秩,讓我們接著看是不是這個(gè)方法
- 看到這里我們基本可以斷定這里就是 OkHttp 攔截器整個(gè)流程的源碼了沪铭,接下來讓我們看看這里面添加了哪些攔截器
到了這里驮肉,我們大致對(duì)這幾個(gè)攔截器有了基本的認(rèn)識(shí),那么問題來了票编,為什么要有這么多攔截器?寫這些攔截器的主要作用是什么登淘?這些攔截器的執(zhí)行流程到底是什么樣的昔榴?
首先 OkHttp 整個(gè)流程是由五個(gè)關(guān)鍵的攔截器完成的吱肌,這五個(gè)攔截器的職責(zé)明確氮墨,從一些攔截器的名稱大概就可以猜出來,例如 CacheInterceptor规揪,從這個(gè)名字我們基本可以猜出來它是負(fù)責(zé)處理請(qǐng)求緩存的奕坟,一套完整的網(wǎng)絡(luò)請(qǐng)求流程很復(fù)雜,需要執(zhí)行幾萬甚至幾十萬行代碼苛萎,如果都寫在一個(gè)類里面可想而知是一件多么恐怖的事情,而攔截器的作用是將這些代碼根據(jù)職責(zé)進(jìn)行分類凹蜂。
至于攔截器的執(zhí)行流程玛痊,我們可以看一下這段代碼
- 我們可以看到,在添加完一些關(guān)鍵的攔截器之后,最終傳入到了一個(gè)攔截鏈中俗或,最后調(diào)用了執(zhí)行的方法岁忘。接下來讓我們看看這個(gè)方法里面做了什么操作
- 接下來讓我們重點(diǎn)分析一下這三句源碼的作用
- 這里有一個(gè)有趣的現(xiàn)象辛慰,一個(gè)類在方法體中 new 了自己,這個(gè)稍微有點(diǎn)難理解干像,但其實(shí)跟遞歸差不多
- 我們可以看到帅腌,攔截鏈會(huì)根據(jù)索引獲取指定位置的攔截器,并且每 new 一個(gè)攔截鏈對(duì)象索引值都會(huì) + 1
最后將攔截鏈對(duì)象傳遞給攔截器麻汰。
等下速客,你剛剛不是說 proceed 方法會(huì)遞歸?遞歸在哪里呢五鲫?
RealInterceptorChain.proceed() -> Interceptor.intercept() -> RealInterceptorChain.proceed() -> Interceptor.intercept() -> 以此類推
等下溺职,你不是說有五個(gè)攔截器,怎么我只看到了兩個(gè)攔截器在調(diào)用位喂?
嗯浪耘,然后呢?還有一個(gè)呢塑崖?去哪里了七冲?
先不要著急,讓我們檢查一下少了哪個(gè)攔截器沒調(diào)用 proceed 方法
沒錯(cuò)规婆,最后一個(gè)攔截器沒調(diào)用 proceed 方法澜躺,那到底是為什么呢?
因?yàn)檫@就是攔截器在調(diào)攔截器的游戲聋呢,假設(shè)總共有五個(gè)攔截器苗踪,第一個(gè)攔截器調(diào)用了第二個(gè)攔截器,第二個(gè)攔截器調(diào)用了第三個(gè)攔截器削锰,第三個(gè)攔截器調(diào)用了第四個(gè)攔截器通铲,第四個(gè)攔截器調(diào)用了第五個(gè)攔截器,那么問題來了器贩,第五個(gè)攔截器要調(diào)用誰颅夺?
沒錯(cuò)朋截,游戲結(jié)束了,沒有再繼續(xù)往下傳遞了吧黄,因?yàn)樗械臄r截器都已經(jīng)遍歷完了
Request 對(duì)象經(jīng)過攔截鏈的層層傳遞部服,直到遍歷完所有的攔截器,也就意味著本次網(wǎng)絡(luò)請(qǐng)求完成了拗慨,最終返回 Response 對(duì)象
至此廓八,攔截器大致的執(zhí)行流程到這里就結(jié)束了,讓我們簡(jiǎn)單總結(jié)一下
源碼總結(jié)
- OkHttp 整個(gè)請(qǐng)求流程是由一條攔截鏈完成赵抢,攔截鏈會(huì)用遞歸的方式來遍歷整個(gè)攔截器列表剧蹂,直到最后一個(gè)攔截器才停止遞歸,等所有的攔截器遍歷完了網(wǎng)絡(luò)請(qǐng)求也就結(jié)束了烦却,然后由攔截鏈返回最終的請(qǐng)求結(jié)果宠叼。