最近看了OkHttp(3.11.0)的源碼,想總結(jié)下自己對(duì)OkHttp的認(rèn)識(shí),加深印象,如有不對(duì)的地方歡迎各位大佬指正。
1、OkHttp簡(jiǎn)單的異步請(qǐng)求。
OkHttpClient okHttpClient = new OkHttpClient();
Request request = new Request.Builder().url(url).build();
Call call = okHttpClient.newCall(request);
call.enqueue(new Callback() {
@Override
public void onResponse(Call call, Response response) throws IOException {
}
@Override
public void onFailure(Call call, IOException e) {
}
});
OkHttp的請(qǐng)求分四步:
- 1.創(chuàng)建OkHttpClient對(duì)象
- 2.創(chuàng)建Request對(duì)象封裝請(qǐng)求url以及請(qǐng)求參數(shù)
- 3.通過(guò)OkhttpClient對(duì)象和Request對(duì)象得到Call對(duì)象
- 4.最終通過(guò)Call對(duì)象來(lái)執(zhí)行請(qǐng)求。
2、通過(guò)跟蹤C(jī)all的enqueue方法探索OkHttp的請(qǐng)求過(guò)程

這里我們會(huì)發(fā)現(xiàn)Call是一個(gè)接口,真正實(shí)現(xiàn)enqueue方法的是RealCall對(duì)象,所以這里展示的也是RealCall的enqueue方法。前面的同步代碼塊主要是防止enqueue方法多次執(zhí)行的,99行主要是將當(dāng)前Call對(duì)象加入到事件監(jiān)聽(tīng)里面。這里核心的是100行。100行又調(diào)用了Dispatcher(Okhttp任務(wù)調(diào)度類(lèi))的equeue方法。然后用Callback對(duì)象創(chuàng)建了AsyncCall對(duì)象。
3、探索AsyncCall類(lèi)的真面目

這里我發(fā)現(xiàn)AsyncCall繼承于NamedRunnable類(lèi)。

而NamedRunnable類(lèi)又是一個(gè)實(shí)現(xiàn)Runnable接口的抽象類(lèi),并在run方法中執(zhí)行了execute方法。而AysbcCall又繼承了NamedRunnable,所以AysncCall也是一個(gè)Runnable,回過(guò)頭再看AysncCall的execute方法,不難發(fā)現(xiàn)這就是AysncCall類(lèi)的核心。
4、回過(guò)頭我們看下Dispatcher的enqueue方法

這是一個(gè)同步的,線(xiàn)程安全的方法。runningAsyncCalls是一個(gè)正在執(zhí)行的存儲(chǔ)AysncCall的隊(duì)列,readyAsyncCalls是一個(gè)等待執(zhí)行的存儲(chǔ)AysncCall的隊(duì)列。maxRequests在Okhttp中定義的正在執(zhí)行最大請(qǐng)求數(shù)是64,支持修改。maxRequestsPerHost在Okhttp中定義的同一主機(jī)請(qǐng)求最大數(shù)為5。所以這段的含義是判斷當(dāng)前正在執(zhí)行的請(qǐng)求數(shù)和與當(dāng)前同一主機(jī)數(shù)是否超過(guò)了最大限制,如果超過(guò)了限制把AysncCall加入到等待執(zhí)行隊(duì)列,否則加入到正在執(zhí)行隊(duì)列,并用線(xiàn)程池執(zhí)行AysncCall,這時(shí)會(huì)調(diào)用AysncCall的execute方法
5、這時(shí)候再看AsyncCall的execute方法

這里的147行是okhttp的核心通過(guò)一系列的攔截器生成最后的返回Response。之后的148行到162行都是判斷此次請(qǐng)求是否成功通過(guò)傳入的CallBack返回請(qǐng)求結(jié)果。164行我們又見(jiàn)到了Dispatcher對(duì)象,在這里調(diào)用了他的finished方法,將當(dāng)前AsyncCall對(duì)象傳了進(jìn)去。這里我們進(jìn)去看下最后調(diào)用的finished方法。


這里202行將當(dāng)前的AysncCall對(duì)象從正在執(zhí)行的請(qǐng)求隊(duì)列runningAsyncCalls中移除了。然后我們主要點(diǎn)進(jìn)去203行看promoteCalls方法。

這里 先是判斷了正在執(zhí)行的請(qǐng)求數(shù)是否大于最大請(qǐng)求數(shù),并且等待執(zhí)行請(qǐng)求隊(duì)列不為空。然后遍歷等待執(zhí)行請(qǐng)求隊(duì)列,取出其中的AsyncCall對(duì)象,判斷當(dāng)前正在執(zhí)行隊(duì)列中與這個(gè)AsyncCall對(duì)象相同的主機(jī)數(shù)有沒(méi)有達(dá)到最大值。如果沒(méi)有的話(huà)則把AsyncCall對(duì)象從等待執(zhí)行隊(duì)列中移除,加入到正在執(zhí)行的隊(duì)列,并用線(xiàn)程池執(zhí)行這個(gè)AsyncCall對(duì)象。
6、總結(jié)Okhttp內(nèi)容進(jìn)行一次網(wǎng)絡(luò)請(qǐng)求流程。
- 1、ReallCall對(duì)象的enqueue方法創(chuàng)建一個(gè)內(nèi)部類(lèi)AysncCall對(duì)象。
- 2、調(diào)用Diapatcher的enqueque方法判斷是否滿(mǎn)足執(zhí)行此AysncCall條件,滿(mǎn)足則將其加入到正在執(zhí)行的請(qǐng)求隊(duì)列中,并開(kāi)始執(zhí)行,不滿(mǎn)足則將其加入到等待執(zhí)行的請(qǐng)求隊(duì)列中。
- 3、AysncCall的execute方法通過(guò)OkHttp一系列的攔截器生成這次請(qǐng)求的Response對(duì)象,通過(guò)CallBack對(duì)象將請(qǐng)求結(jié)果傳遞給調(diào)用者。
- 4、調(diào)用Diapatcher的finished的方法將此AysncCall對(duì)象從正在執(zhí)行的隊(duì)列中移除,遍歷等待執(zhí)行的隊(duì)列,從中取出滿(mǎn)足執(zhí)行條件的AysncCall對(duì)象,將其添加到正在執(zhí)行的隊(duì)列中,并執(zhí)行此AysncCall對(duì)象。如此這樣反復(fù)循環(huán)。
- 5、這里總結(jié)的是一次請(qǐng)求是怎么被分配執(zhí)行的,而請(qǐng)求生成結(jié)果的核心還是在A(yíng)ysncCall的execute方法中的第147行,通過(guò)攔截器鏈生成返回結(jié)果。