OkHttp3 源碼解讀

同步GET請求過程

//HTTP GET
    public String get(String url) throws IOException {
        //新建OKHttpClient客戶端
        OkHttpClient client = new OkHttpClient();
        //新建一個Request對象
        Request request = new Request.Builder()
                .url(url)
                .build();
        //Response為OKHttp中的響應(yīng)
        Response response = client.newCall(request).execute();
        if (response.isSuccessful()) {
            return response.body().string();
        }else{
            throw new IOException("Unexpected code " + response);
        }
    }

第一步 OkHttpClient

OkHttpClient client = new OkHttpClient();

直接上代碼

public OkHttpClient() {
    this(new Builder());
  }
public Builder() {
      dispatcher = new Dispatcher();
      protocols = DEFAULT_PROTOCOLS;
      connectionSpecs = DEFAULT_CONNECTION_SPECS;
      eventListenerFactory = EventListener.factory(EventListener.NONE);
      proxySelector = ProxySelector.getDefault();
      cookieJar = CookieJar.NO_COOKIES;
      socketFactory = SocketFactory.getDefault();
      hostnameVerifier = OkHostnameVerifier.INSTANCE;
      certificatePinner = CertificatePinner.DEFAULT;
      proxyAuthenticator = Authenticator.NONE;
      authenticator = Authenticator.NONE;
      connectionPool = new ConnectionPool();
      dns = Dns.SYSTEM;
      followSslRedirects = true;
      followRedirects = true;
      retryOnConnectionFailure = true;
      connectTimeout = 10_000;
      readTimeout = 10_000;
      writeTimeout = 10_000;
      pingInterval = 0;
    }
Dispatcher dispatcher;  //分發(fā)器
    @Nullable Proxy proxy;  //代理
    List<Protocol> protocols;  //協(xié)議
    List<ConnectionSpec> connectionSpecs;  //傳輸層版本和連接協(xié)議
    final List<Interceptor> interceptors = new ArrayList<>();  //攔截器
    final List<Interceptor> networkInterceptors = new ArrayList<>();  //網(wǎng)絡(luò)攔截器
    EventListener.Factory eventListenerFactory;
    ProxySelector proxySelector; //代理選擇
    CookieJar cookieJar;   //cookie
    @Nullable Cache cache;  //緩存
    @Nullable InternalCache internalCache; //內(nèi)部緩存
    SocketFactory socketFactory; //socket 工廠
    @Nullable SSLSocketFactory sslSocketFactory; //安全套接層socket 工廠,用于HTTPS
    @Nullable CertificateChainCleaner certificateChainCleaner; // 驗證確認響應(yīng)證書 適用 HTTPS 請求連接的主機名。
    HostnameVerifier hostnameVerifier; //  主機名字確認
    CertificatePinner certificatePinner; //  證書鏈
    Authenticator proxyAuthenticator;  //代理身份驗證
    Authenticator authenticator;   // 本地身份驗證
    ConnectionPool connectionPool;  //連接池,復(fù)用連接
    Dns dns;  //域名
    boolean followSslRedirects;  //安全套接層重定向
    boolean followRedirects;  //本地重定向
    boolean retryOnConnectionFailure;  //重試連接失敗
    int connectTimeout;   //連接超時
    int readTimeout;  //read 超時
    int writeTimeout;  //write 超時
    int pingInterval;

new OkHttpClient() 主要實例化Builder ,做的就是初始化一些參數(shù)。

第二步:創(chuàng)建 Request 對象

Request request = new Request.Builder()
.url(url)
.build();

目前流行的Build模式,基本上開源框架都能看到。

Builder(Request request) {
      this.url = request.url;
      this.method = request.method;
      this.body = request.body;
      this.tag = request.tag;
      this.headers = request.headers.newBuilder();
    }

主要還是初始化請求需要的參數(shù),如headers、url等。

第三步: Response 對象

Response response = client.newCall(request).execute();

真正的執(zhí)行 client.newCall().

@Override 
public Call newCall(Request request) {
    return RealCall.newRealCall(this, request, false /* for web socket */);
  }

真正執(zhí)行的是 RealCall.newRealCall()

  private RealCall(OkHttpClient client, Request originalRequest, boolean forWebSocket) {
    this.client = client;
    this.originalRequest = originalRequest;
    this.forWebSocket = forWebSocket;
    this.retryAndFollowUpInterceptor = new RetryAndFollowUpInterceptor(client, forWebSocket);
  }

  static RealCall newRealCall(OkHttpClient client, Request originalRequest, boolean forWebSocket) {
    // Safely publish the Call instance to the EventListener.
    RealCall call = new RealCall(client, originalRequest, forWebSocket);
    call.eventListener = client.eventListenerFactory().create(call);
    return call;
  }
  1. client: 我們當(dāng)前的OkHttpClient。
  2. originalRequest :上面構(gòu)造的Request 對象。
  3. forWebSocket; 是否切換協(xié)議,當(dāng)response回復(fù)101時,會用到。

接下來看下execute() 這是一個同步方法,還有一個異步的執(zhí)行方法enqueue()

@Override
  public Response execute() throws IOException {

    synchronized (this) {

      //  1
      if (executed) throw new IllegalStateException("Already Executed");
      executed = true;
    }
    //2
    captureCallStackTrace();

    //3
    eventListener.callStart(this);
    try {
      // 4
      client.dispatcher().executed(this);

      //5.
      Response result = getResponseWithInterceptorChain();
      if (result == null) throw new IOException("Canceled");
      return result;
    } catch (IOException e) {
      eventListener.callFailed(this, e);
      throw e;
    } finally {
        // 6
      client.dispatcher().finished(this);
    }
  }
  1. 是否執(zhí)行過,一個Call只能執(zhí)行一次.
  2. 創(chuàng)建一個跟蹤堆棧
  3. 開始處理,事件標(biāo)記
  4. 分發(fā)器,文檔里說是異步請求的一個執(zhí)行策略,但是這里是同步,這里只是用來標(biāo)識一下.開始執(zhí)行.
  5. 重點返回Response 對象
  6. 事件標(biāo)記結(jié)束.

重點看getResponseWithInterceptorChain()

Response getResponseWithInterceptorChain() throws IOException {
    // Build a full stack of interceptors.
    //所有的攔截器.
    List<Interceptor> interceptors = new ArrayList<>();
    // 1
    interceptors.addAll(client.interceptors());
    //2
    interceptors.add(retryAndFollowUpInterceptor);
    //3
    interceptors.add(new BridgeInterceptor(client.cookieJar()));
    //4
    interceptors.add(new CacheInterceptor(client.internalCache()));
    //5
    interceptors.add(new ConnectInterceptor(client));
    if (!forWebSocket) {
      //6
      interceptors.addAll(client.networkInterceptors());
    }

    //7
    interceptors.add(new CallServerInterceptor(forWebSocket));
    // 8
    Interceptor.Chain chain = new RealInterceptorChain(interceptors, null, null, null, 0,
        originalRequest, this, eventListener, client.connectTimeoutMillis(),
        client.readTimeoutMillis(), client.writeTimeoutMillis());

    return chain.proceed(originalRequest);
  }
  1. client 自帶的一些自定義攔截器.
  2. 負責(zé)失敗重試以及重定向的攔截器
  3. 負責(zé)把用戶構(gòu)造的請求轉(zhuǎn)換為發(fā)送到服務(wù)器的請求、把服務(wù)器返回的響應(yīng)轉(zhuǎn)換為用戶友好的響應(yīng)的攔截器
  4. 請求從緩存中讀取和通過 responses寫入緩存的攔截器
  5. 打開一個到目標(biāo)服務(wù)器的連接,并繼續(xù)下一個攔截器
  6. 添加client 的網(wǎng)絡(luò)攔截器
  7. 最后一個攔截器,調(diào)用服務(wù)
  8. 創(chuàng)建RealInterceptorChain 并執(zhí)行proceed

RealInterceptorChain中的proceed():

public Response proceed(Request request, StreamAllocation streamAllocation, HttpCodec httpCodec,
      RealConnection connection) throws IOException {
    if (index >= interceptors.size()) throw new AssertionError();

    calls++;

    // If we already have a stream, confirm that the incoming request will use it.
    if (this.httpCodec != null && !this.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.httpCodec != null && calls > 1) {
      throw new IllegalStateException("network interceptor " + interceptors.get(index - 1)
          + " must call proceed() exactly once");
    }

    // Call the next interceptor in the chain.
    //1
    RealInterceptorChain next = new RealInterceptorChain(interceptors, streamAllocation, httpCodec,
        connection, index + 1, request, call, eventListener, connectTimeout, readTimeout,
        writeTimeout);

    //2
    Interceptor interceptor = interceptors.get(index);
    //3
    Response response = interceptor.intercept(next);

    // Confirm that the next interceptor made its required call to chain.proceed().
    if (httpCodec != 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;
  }
  1. 在chain 中調(diào)用下一個攔截器.
  2. 獲取下一個攔截器,在除了Clien之外的第一個攔截器就是RetryAndFollowUpInterceptor
  3. 執(zhí)行攔截器
RetryAndFollowUpInterceptor
@Override public Response intercept(Chain chain) throws IOException {
    Request request = chain.request(); // 獲取Request
    RealInterceptorChain realChain = (RealInterceptorChain) chain;  //獲取Chain
    Call call = realChain.call();  // 獲取Call對象
    EventListener eventListener = realChain.eventListener();  // 獲取事件集合

    streamAllocation = new StreamAllocation(client.connectionPool(), createAddress(request.url()),
        call, eventListener, callStackTrace);

    int followUpCount = 0;
    Response priorResponse = null;
    while (true) {
      //當(dāng)連接被取消時釋放連接
      if (canceled) {
        streamAllocation.release();
        throw new IOException("Canceled");
      }

      Response response;
      boolean releaseConnection = true;
      try {
        //1
        response = realChain.proceed(request, streamAllocation, null, null);
        releaseConnection = false;
      } catch (RouteException e) {
        // The attempt to connect via a route failed. The request will not have been sent.
        if (!recover(e.getLastConnectException(), false, request)) {
          throw e.getLastConnectException();
        }
        releaseConnection = false;
        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, requestSendStarted, request)) throw e;
        releaseConnection = false;
        continue;
      } finally {
        // We're throwing an unchecked exception. Release any resources.
        if (releaseConnection) {
          streamAllocation.streamFailed(null);
          streamAllocation.release();
        }
      }

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

     //3
      Request followUp = followUpRequest(response);

      if (followUp == null) {
        if (!forWebSocket) {
          streamAllocation.release();
        }
        return response;
      }

      closeQuietly(response.body());

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

      if (followUp.body() instanceof UnrepeatableRequestBody) {
        streamAllocation.release();
        throw new HttpRetryException("Cannot retry streamed HTTP body", response.code());
      }

      if (!sameConnection(response, followUp.url())) {
        streamAllocation.release();
        streamAllocation = new StreamAllocation(client.connectionPool(),
            createAddress(followUp.url()), call, eventListener, callStackTrace);
      } else if (streamAllocation.codec() != null) {
        throw new IllegalStateException("Closing the body of " + response
            + " didn't close its backing stream. Bad interceptor?");
      }

      request = followUp;
      priorResponse = response;
    }
  }

這個方法有點長,但是重點是在response = realChain.proceed(request, streamAllocation, null, null);

  1. 執(zhí)行 proceed,這里便是執(zhí)行下一個攔截器,即BridgeInterceptor
  2. 把之前的response附加上去,并把body置為空
  3. 后續(xù)的狀態(tài)碼處理

下一個執(zhí)行的是BridgeInterceptor。

BridgeInterceptor
@Override
  public Response intercept(Chain chain) throws IOException {
    Request userRequest = chain.request();
    Request.Builder requestBuilder = userRequest.newBuilder();

    RequestBody body = userRequest.body(); // 獲取請求體
    if (body != null) {
      MediaType contentType = body.contentType();
      //請求頭:Content-Type
      if (contentType != null) {
        requestBuilder.header("Content-Type", contentType.toString());
      }

      //請求頭:長度
      long contentLength = body.contentLength();
      if (contentLength != -1) {
        requestBuilder.header("Content-Length", Long.toString(contentLength));
        requestBuilder.removeHeader("Transfer-Encoding");
      } else {
        requestBuilder.header("Transfer-Encoding", "chunked");
        requestBuilder.removeHeader("Content-Length");
      }
    }

    //請求頭:主域名
    if (userRequest.header("Host") == null) {
      requestBuilder.header("Host", hostHeader(userRequest.url(), false));
    }

    if (userRequest.header("Connection") == null) {
      requestBuilder.header("Connection", "Keep-Alive");
    }

    // If we add an "Accept-Encoding: gzip" header field we're responsible for also decompressing
    // the transfer stream.
    boolean transparentGzip = false;
    if (userRequest.header("Accept-Encoding") == null && userRequest.header("Range") == null) {
      transparentGzip = true;
      requestBuilder.header("Accept-Encoding", "gzip");
    }

    //cookie
    List<Cookie> cookies = cookieJar.loadForRequest(userRequest.url());
    if (!cookies.isEmpty()) {
      requestBuilder.header("Cookie", cookieHeader(cookies));
    }

    // okhttp 版本
    if (userRequest.header("User-Agent") == null) {
      requestBuilder.header("User-Agent", Version.userAgent());
    }

    //1
    Response networkResponse = chain.proceed(requestBuilder.build());

    HttpHeaders.receiveHeaders(cookieJar, userRequest.url(), networkResponse.headers());

    Response.Builder responseBuilder = networkResponse.newBuilder()
        .request(userRequest);

    if (transparentGzip
        && "gzip".equalsIgnoreCase(networkResponse.header("Content-Encoding"))
        && HttpHeaders.hasBody(networkResponse)) {
      GzipSource responseBody = new GzipSource(networkResponse.body().source());
      Headers strippedHeaders = networkResponse.headers().newBuilder()
          .removeAll("Content-Encoding")
          .removeAll("Content-Length")
          .build();
      responseBuilder.headers(strippedHeaders);
      String contentType = networkResponse.header("Content-Type");
      responseBuilder.body(new RealResponseBody(contentType, -1L, Okio.buffer(responseBody)));
    }

    return responseBuilder.build();
  }

這個攔截器基本上是處理Header的信息。

  1. 執(zhí)行下一個攔截器即CacheInterceptor
CacheInterceptor
@Override public Response intercept(Chain chain) throws IOException {
    Response cacheCandidate = cache != null
        ? cache.get(chain.request())
        : null;

    long now = System.currentTimeMillis();

    CacheStrategy strategy = new CacheStrategy.Factory(now, chain.request(), cacheCandidate).get();
    Request networkRequest = strategy.networkRequest;
    Response cacheResponse = strategy.cacheResponse;

    if (cache != null) {
      cache.trackResponse(strategy);
    }

    if (cacheCandidate != null && cacheResponse == null) {
      closeQuietly(cacheCandidate.body()); // The cache candidate wasn't applicable. Close it.
    }

    // If we're forbidden from using the network and the cache is insufficient, fail.
    //1
    if (networkRequest == null && cacheResponse == null) {
      return new Response.Builder()
          .request(chain.request())
          .protocol(Protocol.HTTP_1_1)
          .code(504)
          .message("Unsatisfiable Request (only-if-cached)")
          .body(Util.EMPTY_RESPONSE)
          .sentRequestAtMillis(-1L)
          .receivedResponseAtMillis(System.currentTimeMillis())
          .build();
    }

    // If we don't need the network, we're done.
    // 2
    if (networkRequest == null) {
      return cacheResponse.newBuilder()
          .cacheResponse(stripBody(cacheResponse))
          .build();
    }

    Response networkResponse = null;
    try {
      // 3
      networkResponse = chain.proceed(networkRequest);
    } finally {
      // If we're crashing on I/O or otherwise, don't leak the cache body.
      if (networkResponse == null && cacheCandidate != null) {
        closeQuietly(cacheCandidate.body());
      }
    }

    // If we have a cache response too, then we're doing a conditional get.
    // 4
    if (cacheResponse != null) {
      if (networkResponse.code() == HTTP_NOT_MODIFIED) {
        Response response = cacheResponse.newBuilder()
            .headers(combine(cacheResponse.headers(), networkResponse.headers()))
            .sentRequestAtMillis(networkResponse.sentRequestAtMillis())
            .receivedResponseAtMillis(networkResponse.receivedResponseAtMillis())
            .cacheResponse(stripBody(cacheResponse))
            .networkResponse(stripBody(networkResponse))
            .build();
        networkResponse.body().close();

        // Update the cache after combining headers but before stripping the
        // Content-Encoding header (as performed by initContentStream()).
        cache.trackConditionalCacheHit();
        cache.update(cacheResponse, response);
        return response;
      } else {
        closeQuietly(cacheResponse.body());
      }
    }

    Response response = networkResponse.newBuilder()
        .cacheResponse(stripBody(cacheResponse))
        .networkResponse(stripBody(networkResponse))
        .build();

    if (cache != null) {
      if (HttpHeaders.hasBody(response) && CacheStrategy.isCacheable(response, networkRequest)) {
        // Offer this request to the cache.
        CacheRequest cacheRequest = cache.put(response);
        return cacheWritingResponse(cacheRequest, response);
      }

      if (HttpMethod.invalidatesCache(networkRequest.method())) {
        try {
          cache.remove(networkRequest);
        } catch (IOException ignored) {
          // The cache cannot be written.
        }
      }
    }

    return response;
  }

這個攔截器主要是緩存相關(guān)的。

  1. 如果禁止使用網(wǎng)絡(luò),并且緩存沒有則失敗.直接拋出504網(wǎng)關(guān)超時
  2. 如果沒有網(wǎng)絡(luò)并且有緩存,直接從cache構(gòu)造一個Response,并且請求結(jié)束.
  3. 執(zhí)行下一個攔截器,ConnectInterceptor。
  4. 如果我們的緩存有一個response,那么將根據(jù)條件來判斷獲取: 如果是304直接從緩存構(gòu)造
ConnectInterceptor
@Override public Response intercept(Chain chain) throws IOException {
    RealInterceptorChain realChain = (RealInterceptorChain) chain;
    Request request = realChain.request();
    StreamAllocation streamAllocation = realChain.streamAllocation();

    // We need the network to satisfy this request. Possibly for validating a conditional GET.
    boolean doExtensiveHealthChecks = !request.method().equals("GET");
    HttpCodec httpCodec = streamAllocation.newStream(client, chain, doExtensiveHealthChecks);
    RealConnection connection = streamAllocation.connection();

    //繼續(xù)下一個攔截器
    return realChain.proceed(request, streamAllocation, httpCodec, connection);
  }

很簡單的一個攔截器打開一個到目標(biāo)服務(wù)器的連接,并繼續(xù)下一個攔截器

CallServerInterceptor
@Override public Response intercept(Chain chain) throws IOException {
    RealInterceptorChain realChain = (RealInterceptorChain) chain;
    HttpCodec httpCodec = realChain.httpStream();
    StreamAllocation streamAllocation = realChain.streamAllocation();
    RealConnection connection = (RealConnection) realChain.connection();
    Request request = realChain.request();

    long sentRequestMillis = System.currentTimeMillis();

    realChain.eventListener().requestHeadersStart(realChain.call());
    httpCodec.writeRequestHeaders(request);
    realChain.eventListener().requestHeadersEnd(realChain.call(), request);

    Response.Builder responseBuilder = null;
    if (HttpMethod.permitsRequestBody(request.method()) && request.body() != null) {
      // If there's a "Expect: 100-continue" header on the request, wait for a "HTTP/1.1 100
      // Continue" response before transmitting the request body. If we don't get that, return
      // what we did get (such as a 4xx response) without ever transmitting the request body.
      if ("100-continue".equalsIgnoreCase(request.header("Expect"))) {
        httpCodec.flushRequest();
        realChain.eventListener().responseHeadersStart(realChain.call());
        responseBuilder = httpCodec.readResponseHeaders(true);
      }

      if (responseBuilder == null) {
        // Write the request body if the "Expect: 100-continue" expectation was met.
        realChain.eventListener().requestBodyStart(realChain.call());
        long contentLength = request.body().contentLength();
        CountingSink requestBodyOut =
            new CountingSink(httpCodec.createRequestBody(request, contentLength));
        BufferedSink bufferedRequestBody = Okio.buffer(requestBodyOut);

        request.body().writeTo(bufferedRequestBody);
        bufferedRequestBody.close();
        realChain.eventListener()
            .requestBodyEnd(realChain.call(), requestBodyOut.successfulCount);
      } else if (!connection.isMultiplexed()) {
        // If the "Expect: 100-continue" expectation wasn't met, prevent the HTTP/1 connection
        // from being reused. Otherwise we're still obligated to transmit the request body to
        // leave the connection in a consistent state.
        streamAllocation.noNewStreams();
      }
    }

    httpCodec.finishRequest();

    if (responseBuilder == null) {
      realChain.eventListener().responseHeadersStart(realChain.call());
      responseBuilder = httpCodec.readResponseHeaders(false);
    }

    Response response = responseBuilder
        .request(request)
        .handshake(streamAllocation.connection().handshake())
        .sentRequestAtMillis(sentRequestMillis)
        .receivedResponseAtMillis(System.currentTimeMillis())
        .build();

    realChain.eventListener()
        .responseHeadersEnd(realChain.call(), response);

    int code = response.code();
    if (forWebSocket && code == 101) {
      // Connection is upgrading, but we need to ensure interceptors see a non-null response body.
      response = response.newBuilder()
          .body(Util.EMPTY_RESPONSE)
          .build();
    } else {
      response = response.newBuilder()
          .body(httpCodec.openResponseBody(response))
          .build();
    }

    if ("close".equalsIgnoreCase(response.request().header("Connection"))
        || "close".equalsIgnoreCase(response.header("Connection"))) {
      streamAllocation.noNewStreams();
    }

    if ((code == 204 || code == 205) && response.body().contentLength() > 0) {
      throw new ProtocolException(
          "HTTP " + code + " had non-zero Content-Length: " + response.body().contentLength());
    }

    return response;
  }

okhttp的最后一個攔截器。通過網(wǎng)絡(luò)調(diào)用服務(wù)。

至此 okhttp的同步調(diào)用 execute()流程走完。

總結(jié)

前面說了攔截器用了責(zé)任鏈設(shè)計模式,它將請求一層一層向下傳,知道有一層能夠得到Resposne就停止向下傳遞,然后將response向上面的攔截器傳遞,然后各個攔截器會對respone進行一些處理,最后會傳到RealCall類中通過execute來得到esponse。

異步GET請求過程

private final OkHttpClient client = new OkHttpClient();

  public void run() throws Exception {
    Request request = new Request.Builder()
        .url(url)
        .build();

    client.newCall(request).enqueue(new Callback() {
      @Override 
      public void onFailure(Call call, IOException e) {
        e.printStackTrace();
      }

      @Override 
      public void onResponse(Call call, Response response) throws IOException {
        if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);

        Headers responseHeaders = response.headers();
        for (int i = 0, size = responseHeaders.size(); i < size; i++) {
          System.out.println(responseHeaders.name(i) + ": " + responseHeaders.value(i));
        }

        System.out.println(response.body().string());
      }
    });
  }

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

這里通過dispatcher的enqueue 調(diào)用異步。

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

解釋: 當(dāng)當(dāng)前運行中的異步請求數(shù)量小于最大數(shù),并且占用的Host數(shù)量小于最大數(shù),則將這個Call加入runningAsyncCalls,并在線程池中運行。否則加入readyAsyncCalls中。

runningAsyncCalls和readyAsyncCalls ?

/** Ready async calls in the order they'll be run. */
  //正在準(zhǔn)備中的異步請求隊列
  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<>();

AsyncCall 是在RealCall中的一個內(nèi)部類》

final class AsyncCall extends NamedRunnable {
    private final Callback responseCallback;

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

    String host() {
      return originalRequest.url().host();
    }

    Request request() {
      return originalRequest;
    }

    RealCall get() {
      return RealCall.this;
    }

    @Override protected void execute() {
      boolean signalledCallback = false;
      try {
        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) {
        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);
      }
    }
  }

通過NamedRunnable 中的run執(zhí)行 execute()

這里的Response還是執(zhí)行g(shù)etResponseWithInterceptorChain()和同步里的一樣。
最后通過 responseCallback 回調(diào)回去。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 134,948評論 18 139
  • 參考資源 官網(wǎng) 國內(nèi)博客 GitHub官網(wǎng) 鑒于一些關(guān)于OKHttp3源碼的解析文檔過于碎片化,本文系統(tǒng)的,由淺入...
    風(fēng)骨依存閱讀 12,559評論 11 82
  • OkHttp源碼的samples的簡單使用的示例: public static void main(String....
    _warren閱讀 825評論 0 1
  • 關(guān)于okhttp是一款優(yōu)秀的網(wǎng)絡(luò)請求框架,關(guān)于它的源碼分析文章有很多,這里分享我在學(xué)習(xí)過程中讀到的感覺比較好的文章...
    蕉下孤客閱讀 3,625評論 2 38
  • 最近我又要開始準(zhǔn)備CATTI的二級筆譯了,感覺長路漫漫。五月底的考試,現(xiàn)在剩下的時間不多了,因為要拋去過年的假期,...
    逆風(fēng)向橘子閱讀 6,451評論 0 0