OkHttp_3.12.0源碼分析

OkHttp_3.12.0源碼分析

基於OkHttp:3.12.0:github.com/square/okht…git

RTFSC

Read The Fucking Source Codegithub

流程分析

  1. 用戶層面調用形式:
OkHttpClient#newCall(new Request())#enquenue(new Callback(){})

複製代碼
  1. OkHttpClient#newCall(new Request()):OkHttpClient根據client、request建立RealCall,RealCall裏面包含全部請求的各類配置信息:攔截器、請求鏈接、調度器Dispatcher、ConnectionPool等
//OkHttpClient
@Override public Call newCall(Request request) {
    return RealCall.newRealCall(this, request, false /* for web socket */);
  }
複製代碼
  1. RealCall#enqueue(new Callback(){}):
    1. 經過RealCall中的client間接獲取Dispatcher--維護一個線程池、readyAsyncCalls、runningAsyncCalls、runningSyncCalls三個請求隊列。
    2. Dispatcher的enqueue會把當前的responseCallback包裝成AsyncCall的形式放入readyAsyncCalls隊列中,注意AsyncCall實現了Runnable接口。
//RealCall
@Override public void enqueue(Callback responseCallback) {
     //其它信息...    
     client.dispatcher().enqueue(new AsyncCall(responseCallback));
  }
  
複製代碼
// Dispatcher    
 void enqueue(AsyncCall call) {
    synchronized (this) {
         readyAsyncCalls.add(call);
        }
        promoteAndExecute();
    } 
複製代碼
  1. Dispatcher#promoteAndExecute:這一步會遍歷readyAsyncCalls把準備隊列中的AsyncCall放到runningAsyncCalls運行隊列中;同時放到立馬執行的一個列表中:executableCalls。這裏一些額外的判斷是:,請求是否超過了最大請求數maxRequests,同一個host是否大於maxRequestsPerHostmaxRequests。
//Dispatcher
    private boolean promoteAndExecute() {
        //...
        List<AsyncCall> executableCalls = new ArrayList<>();
        //僞代碼...
        if(知足必定條件){executableCalls.addAll(readyAsyncCalls)}
    
        for (int i = 0, size = executableCalls.size(); i < size; i++) {
          AsyncCall asyncCall = executableCalls.get(i);
          asyncCall.executeOn(executorService());
        }
    
        return isRunning;
      }
複製代碼
  1. AsyncCall#executeOn(executorService()):web

    1. AsyncCall#executeOn(ExecutorService):經過線程池執行當前對象,會調用上層NamedRunnable的run()方法。重點:這裏完成線程切換邏輯,由於下面就要開始去執行耗時操做。
    2. NamedRunnable#run方法會調用execute(),具體邏輯在子類AsyncCall實現。
    3. AsyncCall#execute()是真正獲取Response值、把值回調給responseCallback的步驟。
//AsyncCall 
   void executeOn(ExecutorService executorService) {
       //...
       executorService.execute(this);//這裏會調用父類的run方法
       //...
   }
複製代碼
//NamedRunnable, AsyncCall的父類  
    public abstract class NamedRunnable implements Runnable {
      //...    
      @Override public final void run() {
        //...
        execute();
      }
      //子類AsyncCall作對應實現
      protected abstract void execute();
    }        
        
複製代碼
#AsyncCall
   @Override protected void execute() {
       boolean signalledCallback = false;
       timeout.enter();
       try {
       //關鍵,去獲取response對象,真正的耗時也就在這
       Response response = getResponseWithInterceptorChain();
       if (retryAndFollowUpInterceptor.isCanceled()) {
           signalledCallback = true;
           //失敗,請求被取消
            responseCallback.onFailure(RealCall.this, new IOException("Canceled"));
       } else {
           signalledCallback = true;
           //成功請求,拿去結果回調
           responseCallback.onResponse(RealCall.this, response);
           }
        } catch (IOException e) {
           e = timeoutExit(e);
           if (signalledCallback) {
             // Do not signal the callback twice!
             Platform.get().log(INFO, "Callback failure for " + toLoggableString(), e);
           } else {
             eventListener.callFailed(RealCall.this, e);
             //失敗,回調
             responseCallback.onFailure(RealCall.this, e);
       }
         } finally {
           //完整結束當前請求,作一些收尾操做
           client.dispatcher().finished(this);
         }
       }
     }
     
複製代碼
  1. RealCall#getResponseWithInterceptorChain:
    1. RealCall#getResponseWithInterceptorChain會把用戶自定義的攔截器、系統級別的攔截器放到list中組裝好,給一個new RealInterceptorChain。這裏須要注意攔截器加入的順序,用戶攔截器優先級最高->系統一些中間攔截->最後網絡請求。
    2. RealInterceptorChain#proceed在這裏會構造一個新的RealInterceptorChain:next,注意新的RealInterceptorChain中index+1;另外根據當前的index取得當前攔截器,執行攔截器中惟一的方法intercept(next),具體執行的哪個呢,就看上層實現的是哪個具體實現。
    3. 咱們隨便看一個實現,假如BridgeInterceptor:會在BridgeInterceptor中執行BridgeInterceptor相關的實現,最關鍵的會執行chain.proceed(requestBuilder.build()),注意Chain是上一個建立的RealInterceptorChain,因此又跑到了第二步,同時index這個時候已經+1,如此完成遞歸操做!
    4. 通過二、3兩步,經過迭代操做,完整全部攔截器的執行。至於說網絡請求、緩存、重試、日誌等等核心包括外圍功能,所有經過攔截器實現,而且責任分明,高度解耦合,實現方式:責任鏈模式。
#RealCall
Response getResponseWithInterceptorChain() throws IOException {
    // Build a full stack of interceptors.
    List<Interceptor> interceptors = new ArrayList<>();
    //用戶添加的自定義攔截器
    interceptors.addAll(client.interceptors());
    //重試
    interceptors.add(retryAndFollowUpInterceptor);
    interceptors.add(new BridgeInterceptor(client.cookieJar()));
    interceptors.add(new CacheInterceptor(client.internalCache()));
    interceptors.add(new ConnectInterceptor(client));
    if (!forWebSocket) {
      interceptors.addAll(client.networkInterceptors());
    }
    interceptors.add(new CallServerInterceptor(forWebSocket));

    Interceptor.Chain chain = new RealInterceptorChain(interceptors, null, null, null, 0,
        originalRequest, this, eventListener, client.connectTimeoutMillis(),
        client.readTimeoutMillis(), client.writeTimeoutMillis());

    return chain.proceed(originalRequest);
  }
  
複製代碼
#RealInterceptorChain
@Override public Response proceed(Request request) throws IOException {
    return proceed(request, streamAllocation, httpCodec, connection);
  }

  public Response proceed(Request request, StreamAllocation streamAllocation, HttpCodec httpCodec,
      RealConnection connection) throws IOException {
    //...
    
    //注意這裏又構造了一個RealInterceptorChain,重點index+1
    RealInterceptorChain next = new RealInterceptorChain(interceptors, streamAllocation, httpCodec,
        connection, index + 1, request, call, eventListener, connectTimeout, readTimeout,
        writeTimeout);
        
    //取當前index對應的攔截器
    Interceptor interceptor = interceptors.get(index);
    //執行取到的攔截器
    Response response = interceptor.intercept(next);
    
    //...
    return response;
  }

複製代碼
# BridgeInterceptor
@Override public Response intercept(Chain chain) throws IOException {
    //根據上游chain繼續處理當前攔截器。注意:chain的源頭:RealInterceptorChain#proceed中建立的next,一個新的RealInterceptorChain
    Request userRequest = chain.request();
    Request.Builder requestBuilder = userRequest.newBuilder();

    //各類邏輯,跳過只看核心...
    
    //核心,這裏又回到了RealInterceptorChain#proceed
    Response networkResponse = chain.proceed(requestBuilder.build());

    //後續邏輯...

    return responseBuilder.build();
  }

複製代碼
相關文章
相關標籤/搜索