1. 程式人生 > >Okhttp原始碼分析--基本使用流程分析

Okhttp原始碼分析--基本使用流程分析

Okhttp原始碼分析--基本使用流程分析

一、 使用

同步請求
    OkHttpClient okHttpClient=new OkHttpClient();
    Request request=new Request.Builder()
        .get()
        .url("www.baidu.com")
        .build();
    Call call =okHttpClient.newCall(request).execute();
非同步請求
  OkHttpClient okHttpClient=new OkHttpClient();
    Request request=new Request.Builder()
        .get()
        .url("www.baidu.com")
        .build();
    Call call=okHttpClient.newCall(request).enqueue(new Callback() {
      @Override public void onFailure(Call call, IOException e) {
        Log.i(TAG, "onFailure: ");
      }

      @Override public void onResponse(Call call, Response response) throws IOException {
        Log.i(TAG, "onResponse: ");
      }
    });

可以看出不管是同步還是非同步請求,使用okhttp大致分為3個步驟:
1. 建立okhttpclient
2. 建立請求的request
3. 通過client拿到call、傳送請求

注:okhttpclient和request的建立均可採用構造者模式,在構造過程中可根據自己的實際需求設定相應的引數,如可在okhttpclient構造時新增自定義攔截器,在request構造過程中設定連線超時時間等。

二、 原始碼分析

首先看下OkhttpClient這個類,使用步驟的第一步就是構造OkhttpClient物件。

先貼下官方對OkhttpClient的定義

 *Factory for {@linkplain Call calls}, which can be used to send HTTP requests and read their
 * responses.
 * OkHttpClients should be shared
 
 * OkHttp performs best when you create a single {@code OkHttpClient} instance and reuse it for
 * all of your HTTP calls. This is because each client holds its own connection pool and thread
 * pools. Reusing connections and threads reduces latency and saves memory. Conversely, creating a
 * client for each request wastes resources on idle pools.

OkhttpClient是用於傳送請求和讀取響應的,官方建議建立一個單例的OkHttpClient,並且所有的http請求都複用它。因為每個OkHttpClient都有自己的connection pool and thread pool。複用connection pool and thread pool可以節約記憶體,相反如果為每個請求都建立一個OkHttpClient那麼會浪費idle pools中的資源。

建立OkHttpClient有兩種方式:
1、通過建構函式
2、通過Builder()建立一個client並自定義設定

同時還提供了一個newBuilder()來自定義client,它跟共享的client擁有相同的connection pool, thread pools, and configuration。我們可以用該方法來獲取特定設定的client。

OkHttpClient提供無參建構函式,由程式碼可知它在內部呼叫OkHttpClient的有參建構函式
,在有參建構函式裡對OkHttpClient主要屬性做了初始化賦值。

  public OkHttpClient() {
    this(new Builder());
  }
  
  OkHttpClient(Builder builder) {
    this.dispatcher = builder.dispatcher;
    this.proxy = builder.proxy;
    this.protocols = builder.protocols;
    this.connectionSpecs = builder.connectionSpecs;
    this.interceptors = Util.immutableList(builder.interceptors);
    this.networkInterceptors = Util.immutableList(builder.networkInterceptors);
    this.eventListenerFactory = builder.eventListenerFactory;
    this.proxySelector = builder.proxySelector;
    this.cookieJar = builder.cookieJar;
    this.cache = builder.cache;
    this.internalCache = builder.internalCache;
    this.socketFactory = builder.socketFactory;
    ...//省略N行
  }

下面貼下OkHttpClient主要的屬性

public class OkHttpClient{
    final Dispatcher dispatcher;//分發器
    final @Nullable Proxy proxy;//代理
    final List<Protocol> protocols;//協議
    final List<ConnectionSpec> connectionSpecs;//傳輸層版本和連線協議
    final List<Interceptor> interceptors;//攔截器 (okhttp核心機制)
    final List<Interceptor> networkInterceptors;//網路攔截器
    final EventListener.Factory eventListenerFactory;
    final ProxySelector proxySelector;//代理選擇器
    final CookieJar cookieJar;//cookie
    final @Nullable
    Cache cache;//cache 快取
    final @Nullable
    InternalCache internalCache;//內部快取
    final SocketFactory socketFactory;//socket 工廠
    final @Nullable
    SSLSocketFactory sslSocketFactory;//安全套層socket工廠 用於https
    final @Nullable
    CertificateChainCleaner certificateChainCleaner;//驗證確認響應書,適用HTTPS 請求連線的主機名
    final HostnameVerifier hostnameVerifier;//主機名字確認
    final CertificatePinner certificatePinner;//證書鏈
    final Authenticator proxyAuthenticator;//代理身份驗證
    final Authenticator authenticator;//本地省份驗證
    final ConnectionPool connectionPool;//連結池 複用連線
    final Dns dns; //域名
    final boolean followSslRedirects;//安全套接層重定向
    final boolean followRedirects;//本地重定向
    final boolean retryOnConnectionFailure;//連線失敗是否重試
    final int connectTimeout;//連線超時時間
    final int readTimeout;//讀取超時時間
    final int writeTimeout;//寫入超時時間
}

通過瀏覽原始碼我們可以發現OkHttpClient採用了構造者設計模式,這樣簡化引數設定,降低使用成本。比如我們前面簡單使用的例子

OkHttpClient類還有一個需要了解的函式就是newCall,因為OkHttpClient實現Call.Factory介面所以覆寫了newCall方法,在方法內部返回的是一個RealCall例項。

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

OkHttpClient構造好了之後接下來就是建立request,request就是我們要傳送的請求。它也是通過builder模式構造的。下面貼下Request的主要屬性以及其建構函式。

public final class Request {
  final HttpUrl url;//請求url地址
  final String method;//請求方式
  final Headers headers;//請求頭
  final @Nullable RequestBody body;//請求body
  final Map<Class<?>, Object> tags;//請求tags用來標記一類請求如 設定之後可以通過tags取消擁有該tag的請求

  Request(Builder builder) {
    this.url = builder.url;
    this.method = builder.method;
    this.headers = builder.headers.build();
    this.body = builder.body;
    this.tags = Util.immutableMap(builder.tags);
  }
  ...
}

通過Request我們可以得到我們想要的請求,然後下一步就是獲取call例項然後傳送請求。
在介紹OkHttpClient類的時候我們已經說過call物件是通過OkHttpClient的newCall方法獲得的實際返回的是RealCall物件,也就是說真正傳送的請求是RealCall,那麼我們來看下RealCall這個類

final class RealCall implements Call {
  final OkHttpClient client; //realcall持有client
  private Transmitter transmitter;//暫時不知道其作用

  /** The application's original request unadulterated by redirects or auth headers. */
  final Request originalRequest;//原始請求
  final boolean forWebSocket;//

  // Guarded by this.
  private boolean executed;//請求是否執行標誌位
  
  private RealCall(OkHttpClient client, Request originalRequest, boolean forWebSocket) { //建構函式
    this.client = client;
    this.originalRequest = originalRequest;
    this.forWebSocket = forWebSocket;
  }

  static RealCall newRealCall(OkHttpClient client, Request originalRequest, boolean forWebSocket) {//okhttpclient即通過該函式返回call
    // Safely publish the Call instance to the EventListener.
    RealCall call = new RealCall(client, originalRequest, forWebSocket);
    call.transmitter = new Transmitter(client, call);
    return call;
  }

RealCall實現的Call介面,其newCall函式內部通過RealCall的建構函式例項化一個call然後返回該call。
最後就是傳送請求了,有兩種方式:同步和非同步。我們先看下同步請求的方式,同步請求是通過execute傳送的

 @Override public Response execute() throws IOException {
    synchronized (this) {//1
      if (executed) throw new IllegalStateException("Already Executed");
      executed = true;
    }
    transmitter.timeoutEnter();
    transmitter.callStart();
    try {
      client.dispatcher().executed(this);//2
      return getResponseWithInterceptorChain();//3
    } finally {
      client.dispatcher().finished(this);//4
    }
  }

execute首先(註釋1處)會synchronized來檢查executed值從而確保每個請求只能執行一次。隨後呼叫dispatcher的executed(註釋2處)。
來看下Dispatcher這個類

public final class Dispatcher {
  private int maxRequests = 64;//最大請求數
  private int maxRequestsPerHost = 5;//每個host的最大請求數
  private @Nullable Runnable idleCallback;//請求佇列空閒回撥

  /** Executes calls. Created lazily. */
  private @Nullable ExecutorService executorService; //執行請求的執行緒池

  /** Ready async calls in the order they'll be run. */
  private final Deque<AsyncCall> readyAsyncCalls = new ArrayDeque<>();//非同步準備就緒請求佇列

  /** Running asynchronous(非同步) calls. Includes canceled calls that haven't finished yet. */
  private final Deque<AsyncCall> runningAsyncCalls = new ArrayDeque<>();//非同步執行請求佇列

  /** Running synchronous calls. Includes canceled calls that haven't finished yet. */
  private final Deque<RealCall> runningSyncCalls = new ArrayDeque<>();//同步請求佇列

可以看出okhttp雖然支援併發請求但是有最大併發請求數的限制。而且okhttp針對不同的請求方式提供了不同的請求佇列。dispatcher這個類主要的作用就是根據request的請求方式以及根據當前client的執行情況把新建立的call請求分發至不同的佇列中去執行。

瞭解了dispatcher類作用我們看下它的exectued函式

 synchronized void executed(RealCall call) {
    runningSyncCalls.add(call);
  }

很簡單它只是把傳入的call物件新增到同步請求佇列中(runningSyncCalls)。那請求具體是如何傳送的呢 我們接著看RealCall的exectued函式。
在註釋3處通過呼叫getResponseWithInterceptorChain()獲取respone並返回該respone。

 Response getResponseWithInterceptorChain() throws IOException {
    // Build a full stack of interceptors.
    List<Interceptor> interceptors = new ArrayList<>();
    interceptors.addAll(client.interceptors());//如果在client中設定了自定義interceptor那麼會放到interceptors中
    interceptors.add(new RetryAndFollowUpInterceptor(client));//新增重試與重定向攔截器
    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));//新增CallServer攔截器
    Interceptor.Chain chain = new RealInterceptorChain(interceptors, transmitter, null, 0,
        originalRequest, this, client.connectTimeoutMillis(),
        client.readTimeoutMillis(), client.writeTimeoutMillis());//
        建立RealInterceptorChain例項,把interceptors傳入

    boolean calledNoMoreExchanges = false;
    try {
      Response response = chain.proceed(originalRequest);//通過proceed鏈式獲取respone
      if (transmitter.isCanceled()) {
        closeQuietly(response);
        throw new IOException("Canceled");
      }
      return response;//返回respone
    } catch (IOException e) {
      calledNoMoreExchanges = true;
      throw transmitter.noMoreExchanges(e);
    } finally {
      if (!calledNoMoreExchanges) {
        transmitter.noMoreExchanges(null);
      }
    }
  }

getResponseWithInterceptorChain首先會把自定義以及okhttp定義的攔截器加到interceptors的list中,然後構造RealInterceptorChain攔截器鏈,呼叫chain.proceed鏈式呼叫各個攔截器並最終獲得respone。

Interceptor可以說是okhttp的核心機制之一,我們一起來看下

public interface Interceptor {
  Response intercept(Chain chain) throws IOException;

  interface Chain {
    Request request();

    Response proceed(Request request) throws IOException;

    /**
     * Returns the connection the request will be executed on. This is only available in the chains
     * of network interceptors; for application interceptors this is always null.
     */
    @Nullable Connection connection();

    Call call();

    int connectTimeoutMillis();

    Chain withConnectTimeout(int timeout, TimeUnit unit);

    int readTimeoutMillis();

    Chain withReadTimeout(int timeout, TimeUnit unit);

    int writeTimeoutMillis();

    Chain withWriteTimeout(int timeout, TimeUnit unit);
  }
}

它是okhttp定義的一個介面類,並且okhttp提供了5個實現類,他們就是getResponseWithInterceptorChain()中新增到interceptors中的5個Interceptor,他們作用各不相同,這個以後會單獨分析。除此之外我們還可以自定義自己的攔截器。
瞭解了攔截器的概念之後我們看下RealInterceptorChain及其proceed函式

public final class RealInterceptorChain implements Interceptor.Chain {
  private final List<Interceptor> interceptors;//攔截器list
  private final Transmitter transmitter;
  private final @Nullable Exchange exchange;
  private final int index;
  private final Request request;//請求
  private final Call call;
  private final int connectTimeout;
  private final int readTimeout;
  private final int writeTimeout;
  private int calls;

  public RealInterceptorChain(List<Interceptor> interceptors, Transmitter transmitter,
      @Nullable Exchange exchange, int index, Request request, Call call,
      int connectTimeout, int readTimeout, int writeTimeout) {//建構函式
    this.interceptors = interceptors;
    this.transmitter = transmitter;
    this.exchange = exchange;
    this.index = index;
    this.request = request;
    this.call = call;
    this.connectTimeout = connectTimeout;
    this.readTimeout = readTimeout;
    this.writeTimeout = writeTimeout;
  }
@Override public Response proceed(Request request) throws IOException {//proceed方法實際呼叫同名的proceed方法
    return proceed(request, transmitter, exchange);
  }

  public Response proceed(Request request, Transmitter transmitter, @Nullable Exchange exchange)
      throws IOException {//1
    if (index >= interceptors.size()) throw new AssertionError();

    calls++;

    // If we already have a stream, confirm that the incoming request will use it.
    if (this.exchange != null && !this.exchange.connection().supportsUrl(request.url())) {
      throw new IllegalStateException("network interceptor " + interceptors.get(index - 1)
          + " must retain the same host and port");
    }

    // If we already have a stream, confirm that this is the only call to chain.proceed().
    if (this.exchange != null && calls > 1) {
      throw new IllegalStateException("network interceptor " + interceptors.get(index - 1)
          + " must call proceed() exactly once");
    }

    // 2
    //Call the next interceptor in the chain.
    RealInterceptorChain next = new RealInterceptorChain(interceptors, transmitter, exchange,
        index + 1, request, call, connectTimeout, readTimeout, writeTimeout);
    Interceptor interceptor = interceptors.get(index);
    Response response = interceptor.intercept(next);

    // Confirm that the next interceptor made its required call to chain.proceed().
    if (exchange != null && index + 1 < interceptors.size() && next.calls != 1) {
      throw new IllegalStateException("network interceptor " + interceptor
          + " must call proceed() exactly once");
    }

    // Confirm that the intercepted response isn't null.
    if (response == null) {
      throw new NullPointerException("interceptor " + interceptor + " returned null");
    }

    if (response.body() == null) {
      throw new IllegalStateException(
          "interceptor " + interceptor + " returned a response with no body");
    }

    return response;
  }

RealInterceptorChain作為攔截器鏈它持有整個應用的攔截器以及網路攔截器。該類的proceed方法實際是呼叫了該類過載的proceed方法(註釋1處)。在註釋2處,呼叫攔截器鏈中的下一個攔截器。在這裡new了一個RealInterceptorChain,注意這裡傳入的index加了1(getResponseWithInterceptorChain傳入的index為0),這代表攔截器鏈中的下一個攔截器的index,之後根據index獲取當前的攔截器並呼叫其intercept方法。intercept是介面Interceptor的一個方法,由具體的實現類實現,此處我們以RetryAndFollowUpInterceptor為例看下intercept方法中做了什麼事情。

public final class RetryAndFollowUpInterceptor implements Interceptor {
  private final OkHttpClient client;//持有的client
@Override public Response intercept(Chain chain) throws IOException {
    Request request = chain.request();//獲取傳入的chain的request 此處的request是next的request
    RealInterceptorChain realChain = (RealInterceptorChain) chain;
    Transmitter transmitter = realChain.transmitter();

    int followUpCount = 0;
    Response priorResponse = null;
    while (true) {
      transmitter.prepareToConnect(request);

      if (transmitter.isCanceled()) {
        throw new IOException("Canceled");
      }

      Response response;
      boolean success = false;
      try {
        response = realChain.proceed(request, transmitter, null);//呼叫next的proceed方法
        success = true;
      } catch (RouteException e) {
        // The attempt to connect via a route failed. The request will not have been sent.
        if (!recover(e.getLastConnectException(), transmitter, false, request)) {
          throw e.getFirstConnectException();
        }
        continue;
      } catch (IOException e) {
        // An attempt to communicate with a server failed. The request may have been sent.
        boolean requestSendStarted = !(e instanceof ConnectionShutdownException);
        if (!recover(e, transmitter, requestSendStarted, request)) throw e;
        continue;
      } finally {
        // The network call threw an exception. Release any resources.
        if (!success) {
          transmitter.exchangeDoneDueToException();
        }
      }

      // Attach the prior response if it exists. Such responses never have a body.
      if (priorResponse != null) {
        response = response.newBuilder()
            .priorResponse(priorResponse.newBuilder()
                    .body(null)
                    .build())
            .build();
      }

      Exchange exchange = Internal.instance.exchange(response);
      Route route = exchange != null ? exchange.connection().route() : null;
      Request followUp = followUpRequest(response, route);//處理請求重定向

      if (followUp == null) {
        if (exchange != null && exchange.isDuplex()) {
          transmitter.timeoutEarlyExit();
        }
        return response;//直到沒有重定向之後返回respone
      }

      RequestBody followUpBody = followUp.body();
      if (followUpBody != null && followUpBody.isOneShot()) {
        return response;
      }

      closeQuietly(response.body());
      if (transmitter.hasExchange()) {
        exchange.detachWithViolence();
      }

      if (++followUpCount > MAX_FOLLOW_UPS) {
        throw new ProtocolException("Too many follow-up requests: " + followUpCount);
      }

      request = followUp;
      priorResponse = response;
    }
  }
}

我們看到在RetryAndFollowUpInterceptor的intercept方法中會呼叫傳入的next(即攔截器鏈中當前攔截器的下一個攔截器)的proceed方法,這樣就可以鏈式的依次呼叫chain中所有攔截器,每個攔截器都執行自己的任務最終返回respone。該respone通過RealCall的getResponseWithInterceptorChain返回到execute方法並最終變成我們獲得的respone。至此同步請求獲得了respone,最後的操作就是在RealCall的execute方法中呼叫finished方法

 @Override public Response execute() throws IOException {
    synchronized (this) {
      if (executed) throw new IllegalStateException("Already Executed");
      executed = true;
    }
    transmitter.timeoutEnter();
    transmitter.callStart();
    try {
      client.dispatcher().executed(this);
      return getResponseWithInterceptorChain();
    } finally {
      client.dispatcher().finished(this);//拿到respone後呼叫finish方法
    }
  }

該方法是dispatcher提供的

 void finished(RealCall call) {
    finished(runningSyncCalls, call);
  }

  private <T> void finished(Deque<T> calls, T call) {
    Runnable idleCallback;
    synchronized (this) {
      if (!calls.remove(call)) throw new AssertionError("Call wasn't in-flight!");//從同步執行佇列移除該call 移除失敗會丟擲異常
      idleCallback = this.idleCallback;
    }

    boolean isRunning = promoteAndExecute();//1

    if (!isRunning && idleCallback != null) {
      idleCallback.run();//如果isRuning為false並且idleCallback不為空就執行idleCallback。
    }
  }

我們看下promoteAndExecute()這個方法

private boolean promoteAndExecute() {
  assert (!Thread.holdsLock(this));

  List<AsyncCall> executableCalls = new ArrayList<>();
  boolean isRunning;
  synchronized (this) {
    for (Iterator<AsyncCall> i = readyAsyncCalls.iterator(); i.hasNext(); ) {//1
      AsyncCall asyncCall = i.next();

      if (runningAsyncCalls.size() >= maxRequests) break; // Max capacity.
      if (asyncCall.callsPerHost().get() >= maxRequestsPerHost) continue; // Host max capacity.

      i.remove();
      asyncCall.callsPerHost().incrementAndGet();
      executableCalls.add(asyncCall);
      runningAsyncCalls.add(asyncCall);
    }
    isRunning = runningCallsCount() > 0;
  }

  for (int i = 0, size = executableCalls.size(); i < size; i++) {//2
    AsyncCall asyncCall = executableCalls.get(i);
    asyncCall.executeOn(executorService());
  }

  return isRunning;
}

該方法主要是兩個for迴圈,首先第一個for迴圈(註釋1處)遍歷準備就緒佇列如果不為空且滿足一定條件則新增到executableCalls中,但是在同步請求時準備就緒佇列(readyAsyncCalls)為空,executableCalls也為空,所以兩個for迴圈都不會進入(實際上該方法是為非同步請求準備的)函式最終返回false。

此時回到dispatcher的finish()方法,它會判斷promoteAndExecute()返回值和idleCallback是否為空,如果isRuning為false並且idleCallback不為空就執行idleCallback,否則就什麼都不做。

至此同步請求流程分析完畢。

非同步請求

非同步請求跟同步請求不同的地方就是它是呼叫RealCall的enqueue方法

@Override public void enqueue(Callback responseCallback) {
    synchronized (this) {
      if (executed) throw new IllegalStateException("Already Executed");
      executed = true;
    }
    transmitter.callStart();
    client.dispatcher().enqueue(new AsyncCall(responseCallback));//執行dispatcher的enqueue
  }

在方法內部呼叫dispatcher的enqueue並傳入AsyncCall引數,我們先來看下AsyncCall再分析非同步請求流程

final class AsyncCall extends NamedRunnable {
  private final Callback responseCallback;
  private volatile AtomicInteger callsPerHost = new AtomicInteger(0);

  AsyncCall(Callback responseCallback) {
    super("OkHttp %s", redactedUrl());
    this.responseCallback = responseCallback;
  }

}

AsyncCall是RealCall的一個內部類它繼承自NamedRunnable

public abstract class NamedRunnable implements Runnable {
  protected final String name;

  public NamedRunnable(String format, Object... args) {
    this.name = Util.format(format, args);
  }

  @Override public final void run() {
    String oldName = Thread.currentThread().getName();
    Thread.currentThread().setName(name);
    try {
      execute();
    } finally {
      Thread.currentThread().setName(oldName);
    }
  }

  protected abstract void execute();
}

NamedRunnable其實就是一個實現Runnable的執行緒類。在它的run方法中呼叫了其提供的抽象函式execute(),execute()的實現是在AsyncCall

@Override protected void execute() {
  boolean signalledCallback = false;
  transmitter.timeoutEnter();
  try {
    Response response = getResponseWithInterceptorChain();
    signalledCallback = true;
    responseCallback.onResponse(RealCall.this, response);
  } catch (IOException e) {
    if (signalledCallback) {
      // Do not signal the callback twice!
      Platform.get().log(INFO, "Callback failure for " + toLoggableString(), e);
    } else {
      responseCallback.onFailure(RealCall.this, e);
    }
  } finally {
    client.dispatcher().finished(this);
  }
}

可以看到這跟同步請求的過程是一樣的先通過getResponseWithInterceptorChain()鏈式呼叫攔截鏈去獲得resopne,之後是通過callback回撥結果,最後呼叫finished。
分析AsyncCall之後我們可以大致猜測出非同步請求的實現是通過執行緒去執行Call,請求的執行過程跟同步請求是一樣的只不過最後是通過callbcak返回。

好了,我們來看下具體的非同步請求流程,之前說到dispatcher的enqueue方法,那我們來看下這個方法都做了什麼

 void enqueue(AsyncCall call) {
    synchronized (this) {
      readyAsyncCalls.add(call);//新增到非同步準備就緒佇列

      // Mutate the AsyncCall so that it shares the AtomicInteger of an existing running call to
      // the same host.
      if (!call.get().forWebSocket) {
        AsyncCall existingCall = findExistingCallWithHost(call.host());
        if (existingCall != null) call.reuseCallsPerHostFrom(existingCall);
      }
    }
    promoteAndExecute();//執行請求
  }

很簡單在方法內部先是把call新增到非同步準備就緒佇列然後呼叫了 promoteAndExecute,promoteAndExecute我們之前在同步請求分析過它內部主要是兩個for迴圈,在同步請求時這兩個for迴圈都是不滿足條件的,那我們看下非同步請求時

private boolean promoteAndExecute() {
    assert (!Thread.holdsLock(this));

    List<AsyncCall> executableCalls = new ArrayList<>();
    boolean isRunning;
    synchronized (this) {
      for (Iterator<AsyncCall> i = readyAsyncCalls.iterator(); i.hasNext(); ) {//把非同步準備就緒對列中的call取出
        AsyncCall asyncCall = i.next();
        //判斷最大請求數以及每個host請求數是否符合要求
        if (runningAsyncCalls.size() >= maxRequests) break; // Max capacity.
        if (asyncCall.callsPerHost().get() >= maxRequestsPerHost) continue; // Host max capacity.
        //移除準備就緒佇列中的call
        i.remove();
        asyncCall.callsPerHost().incrementAndGet();//記錄該call的host的請求數
        executableCalls.add(asyncCall);//新增到executableCalls
        runningAsyncCalls.add(asyncCall);//新增到非同步執行佇列
      }
      isRunning = runningCallsCount() > 0;
    }

    for (int i = 0, size = executableCalls.size(); i < size; i++) {//executableCalls不為空,取出執行
      AsyncCall asyncCall = executableCalls.get(i);
      asyncCall.executeOn(executorService());//call實際執行
    }

    return isRunning;
  }

因為在之前已經把call新增到了非同步準備就緒佇列(readyAsyncCalls
),所以第一個for是可以進入的,在第一個for迴圈內部首先會先判斷當前準備就緒佇列中的call是否達到了最大請求數即最大併發請求數,然後判斷單個host是否達到最大請求數。之後就是把當前的call新增到executableCalls和runningAsyncCalls兩個佇列中。之後進入第二個for迴圈,在這個for迴圈中依次其中取出call物件並呼叫其executeO函式。
注意在execute函式中傳入的executorService其實是一個執行緒池

public synchronized ExecutorService executorService() {
  if (executorService == null) {
    executorService = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60, TimeUnit.SECONDS,
        new SynchronousQueue<>(), Util.threadFactory("OkHttp Dispatcher", false));
  }
  return executorService;
}

可以看出executorService是一個僅有非核心執行緒,且非核心執行緒數無限大的執行緒池。
好了簡單瞭解了executorService我們返回來接著看下executeOn,
在executeOn中呼叫了executorService.execute(this),executeOn是AsyncCall內部的函式而AsyncCall是一個執行緒類所以該操作會執行執行緒的run方法,這裡具體來說就是NamedRunnable的run方法,我們知道在這個run方法中呼叫了execute()方法,execute()我們上面分析過了跟同步請求過程一樣鏈式呼叫攔截器最終獲取respone。

  void executeOn(ExecutorService executorService) {
      assert (!Thread.holdsLock(client.dispatcher()));
      boolean success = false;
      try {
        executorService.execute(this);//實際執行call
        success = true;
      } catch (RejectedExecutionException e) {
        InterruptedIOException ioException = new InterruptedIOException("executor rejected");
        ioException.initCause(e);
        transmitter.noMoreExchanges(ioException);
        responseCallback.onFailure(RealCall.this, ioException);
      } finally {
        if (!success) {
          client.dispatcher().finished(this); // This call is no longer running!
        }
      }
    }

至此非同步請求流程也分析完了。

最後我們來總結下Okhttp的請求流程:
首先不管同步還是非同步都會先初始化一個OkhttpClient之後是Request、Call。
不同之處在於同步請求把請求新增到runningSyncCalls
然後直接呼叫execute,鏈式呼叫攔截器獲取respone並返回。非同步請求則是把請求先新增到readyAsyncCalls,之後執行的時候再把其新增到runningAsyncCalls並且把請求放到子執行緒中取執行,即鏈式呼叫攔截器獲取respone是在子執行緒中完成的。
還有就是不管是同步還是非同步請求完成後都會把Call移除。
以上只是Okhttp最簡單的流程分析,其實Okhttp還有很多值得我們學習的地方,之後我會繼續更新相關內容來更深入瞭解Okhttp。