DEVLOG 1.28 網(wǎng)絡(luò)請求框架(下)-- OkHttp中的Interceptor和Retrofit源碼分析
距離上一篇網(wǎng)絡(luò)請求OkHttp的源碼解析已經(jīng)過去一個月了,我人傻了,時間過得好快,夜幕就要降臨。這篇的內(nèi)容主要是對于Retrofit的源碼分析。雖然OkHttp中還剩下Interceptor,但是OkHttp中的Interceptor我看了一下感覺也沒啥好說的,所以我想在這里簡單說兩句算了。
OkHttp中的Dispatcher將請求放入了線程池,然后由Interceptor進(jìn)行一個責(zé)任鏈的處理,有重試重定向的邏輯的,有構(gòu)建請求頭,取出Cookie的邏輯的等等,主要的網(wǎng)絡(luò)這塊的使用的是Java的Socket api,所以我們在OkHttp這里也看不到特別底層的邏輯。
行,所以重點(diǎn)是放在Retrofit的源碼解析。
本文行文的主要邏輯是順著一個成功的網(wǎng)絡(luò)請求從動態(tài)代理開始,一直到解析完成結(jié)束。
內(nèi)容分成以下章節(jié)
Retrofit實(shí)例的構(gòu)建過程
ServiceMethod以及ServiceMethod的生成
網(wǎng)絡(luò)請求的開始
網(wǎng)絡(luò)返回結(jié)果的解析
Ok,Start your engine!


Retrofit實(shí)例的構(gòu)建過程
Retrofit的實(shí)例我們都是通過builder模式進(jìn)行構(gòu)建,舉個例子:
我們需要配置CallAdapterFactory,這個是將我們的網(wǎng)絡(luò)請求方法的返回值使用Retrofit提供的Call包裝起來;配置ConverterFactory是轉(zhuǎn)化我們的網(wǎng)絡(luò)請求的返回值,比如從json類型變成具體的Java bean。?
下面我們具體的看看build過程
Retrofit#build
通過觀察Retrofit的build過程,我們可以看到Retrofit中被設(shè)置了這樣幾個關(guān)鍵的屬性:

CallFactory:這個就是一個OkHttpClient,如果沒有在構(gòu)建時傳入,會自行初始化。
CallBackExecutor:網(wǎng)絡(luò)請求完成時回調(diào)線程池。在后面查看具體實(shí)現(xiàn)時,在Android中是基于Handler實(shí)現(xiàn)的,將Runnable回調(diào)發(fā)送到主線程
CallAdapterFactory:如果在build過程中添加了Factory,將會構(gòu)建關(guān)于這些Factory的列表。然后將一個默認(rèn)的Factory添加進(jìn)列表的末尾(DefaultCallAdapterFactory)
ConverterFactory:和CallAdapterFactory類似,但是如果沒有傳入定義的Factory,默認(rèn)的列表是空的。 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?? ?
ServiceMethod以及ServiceMethod的生成
下一步我們通常根據(jù)Retrofit的實(shí)例,調(diào)用create方法,通過傳入一個包含了網(wǎng)絡(luò)請求的方法、注解等的接口文件的Class對象。這個過程其實(shí)就是動態(tài)代理的過程。
關(guān)于動態(tài)代理,我們主要看一下Proxy.newProxyInstance中的實(shí)現(xiàn)。首先判斷一下當(dāng)前的方法是否是接口的默認(rèn)方法,如果是,不需要代理;再判斷有無繼承自O(shè)bject的方法,有的話也不用修改它的默認(rèn)實(shí)現(xiàn)。
對于定義在Interface中的空請求方法,Retrofit調(diào)用了loadServiceMethod,首先構(gòu)建ServiceMethod對象。
ServiceMethod就是使用了裝飾模式對于Service類(網(wǎng)絡(luò)請求接口文件)中的方法的包裝。提供了解析注解,調(diào)用CallAdapter執(zhí)行CallAdapt過程(姑且我這么說,其實(shí)就是將返回的數(shù)據(jù)類型使用Call包裝),Converter進(jìn)行解析過程。它在Retrofit中的具體實(shí)現(xiàn)類就是HttpServiceMethod。
Retrofit#loadServiceMethod
這里解析了定義在方法上的注解,將解析完成的請求方法緩存在map中。
綜上所述,大體的框架已經(jīng)搭建好,我們現(xiàn)在知道CallAdapt和Convert過程都在HttpServiceMethod中,我們進(jìn)去看看。
CallAdapt過程的實(shí)現(xiàn)
上面的ServiceMethod.parseAnnotations方法會調(diào)用HttpServiceMethod中的同名方法:
在這個方法中,會使用createCallAdapter從CallAdapterFactory的列表中搜索可用的CallAdapterFactory:
同時也會從ConverterFactory中搜索可以用的Converter。這兩個部分的邏輯比較相似,所以我們著重看CallAdapterFactory這塊的處理。
上面的方法中,第一個get是從Factory列表中獲取合適的工廠類,第二個get是具體的工廠方法的get:
這個方法的返回值是一個CallAdapter對象。可以看到在這個方法中創(chuàng)建的了一個CallAdapter的匿名內(nèi)部類,并且重寫了responseType和adapt方法。adapt方法主要做的就是adapt的過程。我們可以看到具體的Call對象的實(shí)現(xiàn)類是ExecutorCallbackCall這個類。
為了避免大家的邏輯混亂,我們首先看看幾個Call之間的關(guān)系:

在Retrofit中也定義了Call。相對于OkHttp中處理請求的Call,retrofit中的Call是其裝飾。
ExectuorCallbackCall也是一個Call,但是其針對請求的完成會通過executor回調(diào)到主線程:
delegate指的是OkHttpCall,OkHttpCall的enqueue方法也是基于OkHttp中的Call的對應(yīng)方法,可以看到在回調(diào)onResponse時,交給了Executor處理。
這里的Executor是MainThreadExecutor,它將上面的onRepsonse回調(diào)發(fā)送到了主線程執(zhí)行。
網(wǎng)絡(luò)請求的開始和解析
OkHttpCall#enqueue
OkHttpCall這個定義在Retrofit中的類就是對于OkHttp.Call的包裝,也基于了它的enqueue方法:
對于正確返回的數(shù)據(jù)會進(jìn)行解析parseResponse,并且使用Converter轉(zhuǎn)換成正確的Java bean:
到這里一個完整的分析過程就結(jié)束了,上面的流程總結(jié)就是如下的圖:

Retrofit 真的不復(fù)雜~