OkHttp作為時(shí)下最受歡迎的網(wǎng)絡(luò)請(qǐng)求框架之一米同,它有著自己的優(yōu)點(diǎn):
- 使用了眾多的設(shè)計(jì)模式(如:Builder模式、責(zé)任鏈模式等)躯保,尤其是在Interceptor中使用的責(zé)任鏈模式,將整個(gè)網(wǎng)絡(luò)請(qǐng)求串聯(lián)起來最為經(jīng)典。
- 基于Http請(qǐng)求頭专执、DiskLruCache等緩存策略實(shí)現(xiàn)Respose的緩存。
- 內(nèi)部維護(hù)了隊(duì)列線程池郁油,可以輕松實(shí)現(xiàn)并發(fā)任務(wù)本股。
- 擁有自動(dòng)維護(hù)的socket連接池,減少握手次數(shù)桐腌。
除了上面的優(yōu)點(diǎn)拄显,其實(shí)還有很多,這里就不一一詳述了案站。
大家都應(yīng)該知道OkHttp執(zhí)行網(wǎng)絡(luò)請(qǐng)求有兩種方式:
- 1躬审、同步網(wǎng)絡(luò)請(qǐng)求--Call.execute();
- 2.異步網(wǎng)絡(luò)請(qǐng)求--Call.enqueue(Callback responseCallback)。
那么接下來就從這兩個(gè)方面進(jìn)行分析。
1.Call對(duì)象的真實(shí)面貌——RealCall
-
OkHttpClient#newCall():
@Override public Call newCall(Request request) { return new RealCall(this, request, false /* for web socket */); }
從上述代碼忧设,我們發(fā)現(xiàn)Call的實(shí)現(xiàn)類原來是RealCall,并且創(chuàng)建RealCall對(duì)象時(shí)博助,會(huì)需要OkHttpClient、Request以及forWebSocket誊稚。
RealCall詳細(xì)分析:
RealCall構(gòu)造方法
:
構(gòu)造方法中除了會(huì)保存之前的OkHttpClient翔始、Request、boolean forWebSocket之外里伯,還會(huì)創(chuàng)建RetryAndFollowUpIntercptor對(duì)象城瞎,這個(gè)對(duì)象主要作用是在網(wǎng)絡(luò)請(qǐng)求是出現(xiàn)異常情況進(jìn)行重新連接的,具體的分析放在后面疾瓮。-
execute()
同步請(qǐng)求方法:
既然是同步網(wǎng)絡(luò)請(qǐng)求脖镀,那么就意味著不需要為它去執(zhí)行分配線程的操作了。并且它應(yīng)該會(huì)直接進(jìn)入網(wǎng)絡(luò)請(qǐng)求的操作狼电。@Override public Response execute() throws IOException { ... // 通過Dispatcher管理網(wǎng)絡(luò)請(qǐng)求——對(duì)于同步請(qǐng)求只是將其添加到runningSyncCalls隊(duì)列中蜒灰。 client.dispatcher().executed(this); // 構(gòu)建一堆的網(wǎng)絡(luò)請(qǐng)求攔截器 Response result = getResponseWithInterceptorChain(); return result; ... }
-
getResponseWithInterceptorChain()
分析:Response getResponseWithInterceptorChain() throws IOException { // Build a full stack of interceptors. // 1.創(chuàng)建interceptors集合。 List<Interceptor> interceptors = new ArrayList<>(); // 2.添加用戶設(shè)置的所有的interceptors肩碟。 interceptors.addAll(client.interceptors()); // 3.添加錯(cuò)誤重連的Interceptor强窖,此對(duì)象在構(gòu)造方法中被創(chuàng)建。 interceptors.add(retryAndFollowUpInterceptor); // 4.添加BridgeInterceptor攔截器削祈,將用戶設(shè)置的Request進(jìn)行高度封裝(請(qǐng)求頭翅溺、關(guān)于響應(yīng)體的解gzip)脑漫。 interceptors.add(new BridgeInterceptor(client.cookieJar())); // 5.添加處理網(wǎng)絡(luò)請(qǐng)求對(duì)應(yīng)緩存的攔截器 interceptors.add(new CacheInterceptor(client.internalCache())); // 6.添加進(jìn)行Socket連接的攔截器 interceptors.add(new ConnectInterceptor(client)); // 7.添加用戶定義的網(wǎng)絡(luò)攔截器 if (!forWebSocket) { interceptors.addAll(client.networkInterceptors()); } // 8.添加Socket下與服務(wù)器進(jìn)行數(shù)據(jù)讀寫操作的攔截器。 interceptors.add(new CallServerInterceptor(forWebSocket)); // 9.責(zé)任鏈模式中保存了下一攔截器的鏈條對(duì)象(遞歸執(zhí)行的關(guān)鍵)咙崎。 Interceptor.Chain chain = new RealInterceptorChain( interceptors, null, null, null, 0, originalRequest); return chain.proceed(originalRequest); }
構(gòu)建一堆的Interceptor之后优幸,執(zhí)行RealInterceptorChain中的proceed()方法,開啟整個(gè)網(wǎng)絡(luò)請(qǐng)求責(zé)任鏈工作褪猛。
RealInterceptorChain # proceed()源碼分析:
public Response proceed(Request request, StreamAllocation streamAllocation, HttpCodec httpCodec, RealConnection connection) throws IOException { ... // Call the next interceptor in the chain. // 1.創(chuàng)建保存了下一個(gè)interceptor的鏈條對(duì)象网杆。 RealInterceptorChain next = new RealInterceptorChain( interceptors, streamAllocation, httpCodec, connection, index + 1, request); // 2.執(zhí)行當(dāng)前當(dāng)前interceptor的intercept()方法。 Interceptor interceptor = interceptors.get(index); Response response = interceptor.intercept(next); ... return response; }
-
再來分析
enqueue()
異步網(wǎng)絡(luò)請(qǐng)求:既然是異步網(wǎng)絡(luò)請(qǐng)求伊滋,那么肯定需要兩個(gè)條件:
1碳却、網(wǎng)絡(luò)請(qǐng)求的任務(wù)體;
2新啼、執(zhí)行具體任務(wù)的工作線程追城。
@Override public void enqueue(Callback responseCallback) { ... client.dispatcher().enqueue(new AsyncCall(responseCallback)); ... }
-
AsyncCall.execute()源碼分析:
protected void execute() { ... // 我們發(fā)現(xiàn)其實(shí)AsyncCall最后也是做了這件事情 Response response = getResponseWithInterceptorChain(); ... }
2.管理網(wǎng)絡(luò)請(qǐng)求任務(wù)的策略器——Dispatcher
Dispatcher主要的工作就是給異步網(wǎng)絡(luò)請(qǐng)求任務(wù)(AsyncCall)分配工作線程并執(zhí)行。
-
Dispatcher.enqueue()源碼分析:
synchronized void enqueue(AsyncCall call) { // 1.檢測(cè)正在執(zhí)行的異步網(wǎng)絡(luò)請(qǐng)求數(shù)是否小于maxRequests // &&相同主機(jī)的異步網(wǎng)絡(luò)請(qǐng)求數(shù)是否小于maxRequestsPerHost if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) { // 2.滿足條件燥撞,添加到runningAsyncCalls隊(duì)列并且執(zhí)行。 runningAsyncCalls.add(call); executorService().execute(call); } else { // 3.不滿足條件迷帜,添加到readyAsyncCalls物舒。 readyAsyncCalls.add(call); } }
-
Dispatcher.executed()源碼分析:
synchronized void executed(RealCall call) { // 直接添加到runningSyncCalls隊(duì)列 runningSyncCalls.add(call); }
關(guān)于Okhttp的整體工作流程,基本上就是這個(gè)樣子戏锹。至于Interceptor的源碼分析冠胯,會(huì)在后續(xù)的文章中給出。最后把整體流程圖貼出來: