本次閱讀的okhttp原始碼版本為3.7.0
我讀原始碼的習慣是從入口開始看起,所以我們首先看看一次使用okhttp請求的程式碼流程
OkHttpClient okHttpClient = new OkHttpClient();
Request request = new Request.Builder()
.get()
.url("http://www.baidu.com")
.build();
okHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {}
@Override
public void onResponse(Call call, Response response) throws IOException {}
});
複製程式碼
可以看到,一次請求最小元素是newCall()裡面的Call。
可以看到Call只是一個介面而已;需要注意的點已經標紅了- 一個Call,它不能被執行兩次(即enqueue或execute只能呼叫一次)
- 一個Call可以取消,但不是一定能取消,假如請求已完成就不能取消了
具體是為什麼繼續往下看。 在原始碼裡面可以看到RealCall是繼承Call,那麼來看一下RealCall的實現
可以看到每次進行 execute 或 enqueue 的時候都會上鎖然後通過判斷是否執行過該 Call 故重複呼叫會丟擲異常。 那麼接下來我們先看 execute (同步請求),在程式碼中可以看到首先執行了client.dispatcher().executed(call)
這個方法,在最後執行了client.dispatcher().finished(this);
這個方法,那Dispatcher是什麼?
Dispatcher是okhttp中的排程器,請求的執行政策
client.dispatcher().executed(call)
這個方法比較簡單,只是單純的往同步請求佇列新增而已
這裡如果是同步就是簡單的往同步請求佇列移除
接著我們來看最關鍵的 getResponseWithInterceptorChain()
在其中,這個index起到至關重要的作用。所以由上圖我們得知最後會優先執行了攔截器鏈最後的一個攔截器(即上方的CallServerInterceptor攔截器,這個攔截器會進行真正的網路請求),然後再一層層將結果返回給各個攔截器處理。
最後我們再看看非同步請求,執行了client.dispatcher().enqueue(new AsyncCall(responseCallback));
client.dispatcher().executed(call)
這個方法比較簡單,首先判斷正在執行的請求數是否小於設定值(預設值)且與該請求相同主機的請求是否小於設定值(預設值),是則加入執行緒池中並新增進正在請求的佇列;否則加入待請求的佇列。
那看看傳進去的AsyncCall
可以看到基本和同步請求幾乎是一樣的,相當於把同步請求放進runnable裡面然後多了回撥~,~。
好了,本次閱讀到此告一段落