OkHttp面試之--OkHttp的整個非同步請求流程

來源:互聯網
上載者:User

標籤:res   pretty   over   queue   word   ice   調用   遞迴   隊列   

通過上一節,我們已經瞭解了如何使用OkHttp發送非同步請求,下載網狀圖片資訊並顯示到ImageView控制項上,從這一節開始我們就來開始研究一下其內部的實現流程和原理。因為整個流程相對而言還是比較複雜,因此對於流程的分析我劃分成以下幾個章節去介紹

  1. 流程概述
  2. 攔截器的原理
  3. HttpEngine中sendRequest的流程分析
  4. HttpEngine中readResponse的流程分析

這一節我們先來看一下整個流程的概述,先上一張時序圖

以片來自http://www.jianshu.com/p/db197279f053

就從上一些OkHttp的使用開始分析:
上一節我們通過OkHttpClient.newCall(Request)的方法建立出一個Call對象,
Call是一個介面代碼如下:

package okhttp3;import java.io.IOException;public interface Call {  Request request();  Response execute() throws IOException;  void enqueue(Callback responseCallback);  void cancel();  boolean isExecuted();  boolean isCanceled();  interface Factory {    Call newCall(Request request);  }}

因此OkHttpClient需要給我們返回一個Call介面的實作類別,點擊去看一下,代碼如下:

/**   * Prepares the {@code request} to be executed at some point in the future.   */  @Override public Call newCall(Request request) {    return new RealCall(this, request);  }

可以發現,其實返回的是RealCall對象。

接下來在Activity中調用Call.enqueue(Callback)方法,點進去之後代碼如下:

在enqueue一參的方法中又調用了2參數的方法,並將第二個參數forWebSocket置為了false.

而在2參數的enqueue方法中,我們發現最終調用了client.dispatcher.enqueue的方法,並且將Callback和forWebSocket兩個參數封裝到了一個叫做AsyncCall的對象當中.

這個dispatcher就是OkHttpClient中的一個全域變數,點進去查看如下:

synchronized void enqueue(AsyncCall call) {    if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {      runningAsyncCalls.add(call);      executorService().execute(call);    } else {      readyAsyncCalls.add(call);    }  }

Dispatcher內部是過一個線程池來執行,超過最大請求數後則先加入準備請求的隊列中,對於這個線程池後續會單獨用一篇部落格來講解,此時我們主要來整理一下整個請求流程,因此不做過多解釋。 以上代碼會執行到if代碼塊,然後執行executorService().execute(call); 看到這對於線程池有瞭解的同學應該能立馬想到AsyncCall其實就是一個Runnable對象,我們點進AsyncCall代碼中可以看到它就是繼承了NamedRunnable,而NamedRunnable又實現了Runnable介面並且在run方法中主動調用了execute的方法,如下所示:

而這個抽象的execute方法在AsyncCall中已經被實現,如下所示:

由可以看到,當執行一個AsyncCall的execute方法時,會調用一個叫做getResponseWithInterceptorChain的方法,並返回Response對象,然後通過介面回調的方式將此Response返回給我們在Activity中所實現的Callback介面並重新整理UI。

那這個getResponseWithInterceptorChain內部又是如何工作的呢??其實這個方法中的源碼很簡單,如下所示:

建立了一個ApplicationInterceptorChain對象,然後調用其proceed方法進行,接下來看一下ApplicationInterceptorChain的proceed代碼如下

在proceed方法中,判斷如果index小於OkHttpClient中攔截器集合的個數,則會遞迴建立新的ApplicationInterceptorChain對象,並將這個新的ApplicationInterceptorChain對象那個傳遞給index下標的攔截器的intercept方法

注意:此處有一個亮點,如果我們想自己實現Intercept一定要在intercept方法中主動調用chain.proceed方法,這樣整個遞迴迴圈才能順利的執行下去,反過來說我們也可以在某一個攔截器中將網路請求進行攔截,做法就是只要在攔截器中不調用proceed方法即可

對於攔截器的作用以及原理我會在後續章節中單獨分析


但是在這個遞迴迴圈中,最終index都會處於一個>=client.interceptors.size的階段,因此最終會調用最後一行代碼getResponse(request, forWebSocket)方法。這個方法是真正的發送網路請求並擷取Response的方法,其內部代碼如下所示:

,在getResponse方法中建立了一個HttpEngine的對象,然後分別調用HttpEngine的sendRequest和readResponse方法,這兩個方法依次是發送網路請求和讀取網路請求結果,最後將Response對象返回到之前說的getResponseWithInterceptorChain方法,並回傳給Activity中的Callback

對於HttpEngine內部實現後續會單獨再做分析。

最後用兩個圖來做一個流程總結




OkHttp面試之--OkHttp的整個非同步請求流程

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.