OKHttp源碼解析(一)--初階

這段時(shí)間老李的新公司要更換網(wǎng)絡(luò)層,知道現(xiàn)在主流網(wǎng)絡(luò)層的模式是RxJava+Retrofit+OKHttp,所以老李開始研究這三個(gè)項(xiàng)目的源代碼,在更換網(wǎng)絡(luò)層后,開始分享這個(gè)三個(gè)項(xiàng)目源碼的分析。*
本篇文章 主要講解OKHttp源碼解析(3.7.0)
OKHttp官網(wǎng)
github地址
本文大體上分為11個(gè)部分

本篇文章的主要內(nèi)容如下:

    1. OkHttp介紹
    1. OkHttp使用
    1. OkHttp流程源碼跟蹤

一、OKHTTP簡(jiǎn)介

  • 1.支持HTTP2/SPDY
  • 2.socket自動(dòng)選擇最好路線,并支持自動(dòng)重連
  • 3.擁有自動(dòng)維護(hù)的socket連接池,減少握手次數(shù)
  • 4.擁有隊(duì)列線程池,輕松寫并發(fā)
  • 5.擁有Interceptors輕松處理請(qǐng)求與響應(yīng)(比如透明GZIP壓縮)基于Headers的緩存策略

二、OKHTTP使用:

1、GET請(qǐng)求

  OkHttpClient client = new OkHttpClient();

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

  Response response = client.newCall(request).execute();
  return response.body().string();
}

2、POST請(qǐng)求

   public static final MediaType JSON
    = MediaType.parse("application/json; charset=utf-8");

  OkHttpClient client = new OkHttpClient();

  RequestBody body = RequestBody.create(JSON, json);

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

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

  return response.body().string();
}

三、OKHTTP源碼流程分析

(一)、OKHTTP 同步請(qǐng)求debug代碼跟蹤:

  OkHttpClient client = new OkHttpClient();
  Request request = new Request.Builder()
      .url(url)
      .build();
  Response response = client.newCall(request).execute();

從上面代碼所示,先是new了一個(gè)OKHttpClient對(duì)象。

1、OKHttpClient類詳解

OKHttpClient類就比較簡(jiǎn)單了:

  • 1、里面包含了很多對(duì)象,其實(shí)OKhttp的很多功能模塊都包裝進(jìn)這個(gè)類,讓這個(gè)類單獨(dú)提供對(duì)外的API,這種外觀模式的設(shè)計(jì)十分的優(yōu)雅。外觀模式。
  • 2、而內(nèi)部模塊比較多,就使用了Builder模式(建造器模式)。Builder模式(建造器模式)
  • 3、它的方法只有一個(gè):newCall.返回一個(gè)Call對(duì)象(一個(gè)準(zhǔn)備好了的可以執(zhí)行和取消的請(qǐng)求)。

而大家仔細(xì)讀源碼又會(huì)發(fā)現(xiàn)構(gòu)造了OKHttpClient后又new了一個(gè)Rquest對(duì)象。那么咱們就來看下Request,說道Request又不得不提Response。所以咱們一起講了

2、Request、Response類詳解

Request Response

  • 1、Request、Response分別抽象成請(qǐng)求和相應(yīng)
  • 2、其中Request包括Headers和RequestBody,而RequestBody是abstract的,他的子類是有FormBody (表單提交的)和 MultipartBody(文件上傳),分別對(duì)應(yīng)了兩種不同的MIME類型
    FormBody :"application/x-www-form-urlencoded"
    MultipartBody:"multipart/"+xxx.
  • 3、其中Response包括Headers和RequestBody,而ResponseBody是abstract的,所以他的子類也是有兩個(gè):RealResponseBody和CacheResponseBody,分別代表真實(shí)響應(yīng)和緩存響應(yīng)。
  • 4、由于RFC協(xié)議規(guī)定,所以所有的頭部信息不是隨便寫的,request的header與response的header的標(biāo)準(zhǔn)都不同。具體的見 List of HTTP header fields。OKHttp的封裝類Request和Response為了應(yīng)用程序編程方便,會(huì)把一些常用的Header信息專門提取出來,作為局部變量。比如contentType,contentLength,code,message,cacheControl,tag...它們其實(shí)都是以name-value對(duì)的形勢(shì),存儲(chǔ)在網(wǎng)絡(luò)請(qǐng)求的頭部信息中。

根據(jù)從上面的GET請(qǐng)求,顯示用builder構(gòu)建了Request對(duì)象,然后執(zhí)行了OKHttpClient.java的newCall方法,那么咱們就看看這個(gè)newCall里面都做什么操作?

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

Call是個(gè)什么東西,那咱們看下Call這個(gè)類

3、Call類詳解

Call: HTTP請(qǐng)求任務(wù)封裝
可以說我們能用到的操縱基本上都定義在這個(gè)接口里面了,所以也可以說這個(gè)類是OKHttp類的核心類了。我們可以通過Call對(duì)象來操作請(qǐng)求了。而Call接口內(nèi)部提供了Factory工廠方法模式(將對(duì)象的創(chuàng)建延遲到工廠類的子類去進(jìn)行,從而實(shí)現(xiàn)動(dòng)態(tài)配置)
Call接口提供了內(nèi)部接口Factory(用于將對(duì)象的創(chuàng)建延遲到該工廠類的子類中進(jìn)行,從而實(shí)現(xiàn)動(dòng)態(tài)的配置).

/**
 * A call is a request that has been prepared for execution. A call can be canceled. As this object
 * represents a single request/response pair (stream), it cannot be executed twice.
 */
public interface Call extends Cloneable {
  /** Returns the original request that initiated this call. */
  Request request();

  /**
   * Invokes the request immediately, and blocks until the response can be processed or is in
   * error.
   *
   * <p>To avoid leaking resources callers should close the {@link Response} which in turn will
   * close the underlying {@link ResponseBody}.
   *
   * <pre>@{code
   *
   *   // ensure the response (and underlying response body) is closed
   *   try (Response response = client.newCall(request).execute()) {
   *     ...
   *   }
   *
   * }</pre>
   *
   * <p>The caller may read the response body with the response's {@link Response#body} method. To
   * avoid leaking resources callers must {@linkplain ResponseBody close the response body} or the
   * Response.
   *
   * <p>Note that transport-layer success (receiving a HTTP response code, headers and body) does
   * not necessarily indicate application-layer success: {@code response} may still indicate an
   * unhappy HTTP response code like 404 or 500.
   *
   * @throws IOException if the request could not be executed due to cancellation, a connectivity
   * problem or timeout. Because networks can fail during an exchange, it is possible that the
   * remote server accepted the request before the failure.
   * @throws IllegalStateException when the call has already been executed.
   */
  Response execute() throws IOException;

  /**
   * Schedules the request to be executed at some point in the future.
   *
   * <p>The {@link OkHttpClient#dispatcher dispatcher} defines when the request will run: usually
   * immediately unless there are several other requests currently being executed.
   *
   * <p>This client will later call back {@code responseCallback} with either an HTTP response or a
   * failure exception.
   *
   * @throws IllegalStateException when the call has already been executed.
   */
  void enqueue(Callback responseCallback);

  /** Cancels the request, if possible. Requests that are already complete cannot be canceled. */
  void cancel();

  /**
   * Returns true if this call has been either {@linkplain #execute() executed} or {@linkplain
   * #enqueue(Callback) enqueued}. It is an error to execute a call more than once.
   */
  boolean isExecuted();

  boolean isCanceled();

  /**
   * Create a new, identical call to this one which can be enqueued or executed even if this call
   * has already been.
   */
  Call clone();

  interface Factory {
    Call newCall(Request request);
  }
}

在源碼中,OKHttpClient實(shí)現(xiàn)了Call.Factory接口,返回了一個(gè)RealCall對(duì)象。那我們就來看下RealCall這個(gè)類

4、RealCall類詳解

RealCall

  • 1、OkHttpClient的newCall方法里面new了RealCall的對(duì)象,但是RealCall的構(gòu)造函數(shù)需要傳入一個(gè)OKHttpClient對(duì)象和Request對(duì)象(PS:第三個(gè)參數(shù)false表示不是webSokcet).因此RealCall包裝了Request對(duì)象。所以RealCall可以很方便地使用這兩個(gè)對(duì)象。
  • 2、RealCall里面的兩個(gè)關(guān)鍵方法是:execute 和 enqueue。分別用于同步和異步得執(zhí)行網(wǎng)絡(luò)請(qǐng)求。
  • 3、RealCall還有一個(gè)重要方法是:getResponseWithInterceptorChain,添加攔截器,通過攔截器可以將一個(gè)流式工作分解為可配置的分段流程,既增加了靈活性也實(shí)現(xiàn)了解耦,關(guān)鍵還可以自有配置,非常完美。

所以client.newCall(request).execute();實(shí)際上執(zhí)行的是RealCall的execute方法,現(xiàn)在咱們?cè)倩貋砜聪翿ealCall的execute的具體實(shí)現(xiàn)

    @Override
    public Response execute() throws IOException {
        synchronized (this) {
            if (executed) throw new IllegalStateException("Already Executed");
            executed = true;
        }
        captureCallStackTrace();
        try {
            client.dispatcher().executed(this);
            Response result = getResponseWithInterceptorChain();
            if (result == null) throw new IOException("Canceled");
            return result;
        } finally {
            client.dispatcher().finished(this);
        }
    }

首先是

        synchronized (this) {
            if (executed) throw new IllegalStateException("Already Executed");
            executed = true;
        }

判斷call是否執(zhí)行過,可以看出每個(gè)Call對(duì)象只能使用一次原則。然后調(diào)用了captureCallStackTrace()方法。
RealCall.java

  private void captureCallStackTrace() {
    Object callStackTrace = Platform.get().getStackTraceForCloseable("response.body().close()");
    retryAndFollowUpInterceptor.setCallStackTrace(callStackTrace);
  }

RealCall的captureCallStackTrace() 又調(diào)用了Platform.get().getStackTraceForCloseable()

public class Platform {
  public static Platform get() {
    return PLATFORM;
  }
  /**
   * Returns an object that holds a stack trace created at the moment this method is executed. This
   * should be used specifically for {@link java.io.Closeable} objects and in conjunction with
   * {@link #logCloseableLeak(String, Object)}.
   */
  public Object getStackTraceForCloseable(String closer) {
    if (logger.isLoggable(Level.FINE)) {
      return new Throwable(closer); // These are expensive to allocate.
    }
    return null;
  }
}

其實(shí)是調(diào)用AndroidPlatform. getStackTraceForCloseable(String closer)方法。這里就不詳細(xì)說了,后面詳細(xì)說。
然后retryAndFollowUpInterceptor.setCallStackTrace(),在這個(gè)方法里面什么都沒做就是set一個(gè)object進(jìn)去

public final class RetryAndFollowUpInterceptor implements Interceptor {
  public void setCallStackTrace(Object callStackTrace) {
    this.callStackTrace = callStackTrace;
  }
}

綜上所示captureCallStackTrace()這個(gè)方法其實(shí)是捕獲了這個(gè)請(qǐng)求的StackTrace。
然后進(jìn)入了第一個(gè)核心類---Dispatcher的的execute方法了,由于下面是進(jìn)入了關(guān)鍵部分,所以重點(diǎn)講解下,代碼如何:

    try {
      client.dispatcher().executed(this);
      Response result = getResponseWithInterceptorChain();
      if (result == null) throw new IOException("Canceled");
      return result;
    } finally {
      client.dispatcher().finished(this);
    }

看下OKHttpClient的dispatcher()方法的具體內(nèi)容如下圖

 //OKHttpClient.java
  public Dispatcher dispatcher() {
    return dispatcher;
  }

大家發(fā)現(xiàn)client.dispatcher()返回的是Dispatcher對(duì)象,那么這個(gè)Dispatcher對(duì)象是何時(shí)創(chuàng)建的那?在OkHttpClient.java里面Build類里面的構(gòu)造函數(shù)里面,如下圖

//OkHttpClient.java
public static final class Builder {
   //其它代碼先忽略掉
    public Builder() {
      dispatcher = new Dispatcher();
      //其它代碼先忽略掉
    }
}

所以默認(rèn)執(zhí)行Builder()放到時(shí)候就創(chuàng)建了一個(gè)Dispatcher。那么咱們看下dispatcher里面的execute()是如何處理的

  /** Used by {@code Call#execute} to signal it is in-flight. */
  synchronized void executed(RealCall call) {
    runningSyncCalls.add(call);
  }

里面發(fā)現(xiàn)是runningSyncCalls執(zhí)行了add方法莫非runningSyncCalls是個(gè)list,咱們查看dispatcher里面怎么定義runningSyncCalls的。

  /** 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<>();

原來runningSyncCalls是雙向隊(duì)列啊,突然發(fā)現(xiàn)Dispatcher里面定義了三個(gè)雙向隊(duì)列,看下注釋,我們大概能明白readyAsyncCalls 是一個(gè)存放了等待執(zhí)行任務(wù)Call的雙向隊(duì)列,runningAsyncCalls是一個(gè)存放異步請(qǐng)求任務(wù)Call的雙向任務(wù)隊(duì)列,runningSyncCalls是一個(gè)存放同步請(qǐng)求的雙向隊(duì)列。關(guān)于隊(duì)列咱們?cè)谙缕恼吕锩嬖敿?xì)介紹。

執(zhí)行完client.dispatcher().executed(this);要走到getResponseWithInterceptorChain();方法了里面了,看下這個(gè)方法是具體做什么的?

  Response getResponseWithInterceptorChain() throws IOException {
    // Build a full stack of interceptors.
    List<Interceptor> interceptors = new ArrayList<>();
    //添加開發(fā)者應(yīng)用層自定義的Interceptor
    interceptors.addAll(client.interceptors());
    //這個(gè)Interceptor是處理請(qǐng)求失敗的重試,重定向    
    interceptors.add(retryAndFollowUpInterceptor);
    //這個(gè)Interceptor工作是添加一些請(qǐng)求的頭部或其他信息
    //并對(duì)返回的Response做一些友好的處理(有一些信息你可能并不需要)
    interceptors.add(new BridgeInterceptor(client.cookieJar()));
    //這個(gè)Interceptor的職責(zé)是判斷緩存是否存在,讀取緩存,更新緩存等等
    interceptors.add(new CacheInterceptor(client.internalCache()));
    //這個(gè)Interceptor的職責(zé)是建立客戶端和服務(wù)器的連接
    interceptors.add(new ConnectInterceptor(client));
    if (!forWebSocket) {
      //添加開發(fā)者自定義的網(wǎng)絡(luò)層攔截器
      interceptors.addAll(client.networkInterceptors());
    }
    interceptors.add(new CallServerInterceptor(forWebSocket));
    //一個(gè)包裹這request的chain
    Interceptor.Chain chain = new RealInterceptorChain(
        interceptors, null, null, null, 0, originalRequest);
    //把chain傳遞到第一個(gè)Interceptor手中
    return chain.proceed(originalRequest);
  }

發(fā)現(xiàn) new了一個(gè)ArrayList,然后就是不斷的add,后面 new了 RealInterceptorChain對(duì)象,最后調(diào)用了chain.proceed()方法。先看下RealInterceptorChain的構(gòu)造函數(shù)。

 public RealInterceptorChain(List<Interceptor> interceptors, StreamAllocation streamAllocation,
      HttpCodec httpCodec, RealConnection connection, int index, Request request) {
    this.interceptors = interceptors;
    this.connection = connection;
    this.streamAllocation = streamAllocation;
    this.httpCodec = httpCodec;
    this.index = index;
    this.request = request;
  }

發(fā)現(xiàn)什么都沒做就是做了賦值操作,后面跟蹤下chain.proceed()方法
由于Interceptor是個(gè)接口,所以應(yīng)該是具體實(shí)現(xiàn)類RealInterceptorChain的proceed實(shí)現(xiàn)

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

  interface Chain {
    Request request();

    Response proceed(Request request) throws IOException;

    Connection connection();
  }
}
public final class RealInterceptorChain implements Interceptor.Chain{
  Response intercept(Chain chain) throws IOException;

      @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 {
        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.
        RealInterceptorChain next = new RealInterceptorChain(
                interceptors, streamAllocation, httpCodec, connection, index + 1, request);
        Interceptor interceptor = interceptors.get(index);
        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");
        }

        return response;
    }

}

由于在構(gòu)造RealInterceptorChain對(duì)象時(shí)候httpCodec直接賦予了null,所以下面代碼直接略過。

   // 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");
    }

然后看到在proceed方面里面又new了一個(gè)RealInterceptorChain類的next對(duì)象,溫馨提示下,里面的streamAllocation, httpCodec, connection都是null,所以這個(gè)next對(duì)象和chain最大的區(qū)別就是index屬性值不同chain是0.而next是1,然后取interceptors下標(biāo)為1的對(duì)象的interceptor。由從上文可知,如果沒有開發(fā)者自定義的Interceptor時(shí),首先調(diào)用的RetryAndFollowUpInterceptor,如果有開發(fā)者自己定義的interceptor則調(diào)用開發(fā)者interceptor。

這里重點(diǎn)說一下,由于后面的interceptor比較多,且涉及的也是重要的部分,而咱們這里主要是講流程,所以這里就不詳細(xì)和大家說了,由后面再詳細(xì)講解,后面的流程是在每一個(gè)interceptor的intercept方法里面都會(huì)調(diào)用chain.proceed()從而調(diào)用下一個(gè)interceptorintercept(next)方法,這樣就可以實(shí)現(xiàn)遍歷getResponseWithInterceptorChain里面interceptors的item,實(shí)現(xiàn)遍歷循環(huán),縮減后的代碼如下:

  //RetryAndFollowUpInterceptor.java
public Response intercept(Chain chain) throws IOException {
 //忽略部分代碼
 response = ((RealInterceptorChain) chain).proceed(request, streamAllocation, null, null);
 //忽略部分代碼
}
 
//BridgeInterceptor.java
public Response intercept(Chain chain) throws IOException {
  //忽略部分代碼
  Response networkResponse = chain.proceed(requestBuilder.build());
  //忽略部分代碼
}
//CacheInterceptor.java
public Response intercept(Chain chain) throws IOException {
   //忽略部分代碼
   networkResponse = chain.proceed(networkRequest);
   //忽略部分代碼
}
//ConnectInterceptor.java
public Response intercept(Chain chain) throws IOException {
     //忽略部分代碼
     return realChain.proceed(request, streamAllocation, httpCodec, connection);
}

讀過源碼我們知道getResponseWithInterceptorChain里面interceptors的最后一個(gè)item是CallServerInterceptor.java,最后一個(gè)Interceptor(即CallServerInterceptor)里面是直接返回了response 而不是進(jìn)行繼續(xù)遞歸,具體里面是通過OKio實(shí)現(xiàn)的,具體代碼,等后面再詳細(xì)說明,CallServerInterceptor返回response后返回給上一個(gè)interceptor,一般是開發(fā)者自己定義的networkInterceptor,然后開發(fā)者自己的networkInterceptor把他的response返回給前一個(gè)interceptor,依次以此類推返回給第一個(gè)interceptor,這時(shí)候又回到了realCall里面的execute()里面了,代碼如下:

  @Override 
  public Response execute() throws IOException {
    synchronized (this) {
      if (executed) throw new IllegalStateException("Already Executed");
      executed = true;
    }
    captureCallStackTrace();
    try {
      client.dispatcher().executed(this);
      Response result = getResponseWithInterceptorChain();
      if (result == null) throw new IOException("Canceled");
      return result;
    } finally {
      client.dispatcher().finished(this);
    }
  }
最后把response返回給get請(qǐng)求的返回值。至此整體GET請(qǐng)求的大體流程就已經(jīng)結(jié)束了。(PS:最后別忘記走client.dispatcher().finished(this))

大體流程如下圖:

image.png

(二)、OKHTTP 異步請(qǐng)求debug代碼跟蹤:

OkHttpClient client = new OkHttpClient();

String run(String url) throws IOException {
  Request request = new Request.Builder()
      .url(url)
      .build();

  Response response = client.newCall(request).enqueue(new Callback() {
        @Override
        public void onFailure(Call call, IOException e) {
        }
        @Override
        public void onResponse(Call call, Response response) throws IOException {
        }
    });

前面和同步一樣new了一個(gè)OKHttp和Request。這塊和同步一樣就不說了,那么說說和同步不一樣的地方,后面異步進(jìn)入enqueue()方法

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

由于executed默認(rèn)為false,所以先進(jìn)行判斷是否為true,為true則直接跑異常,沒有則設(shè)置為true,可以看出executed這個(gè)是一個(gè)標(biāo)志,標(biāo)志這個(gè)請(qǐng)求是否已經(jīng)正在請(qǐng)求中,合同步一樣先調(diào)用了captureCallStackTrace();然后調(diào)用 client.dispatcher().enqueue(new AsyncCall(responseCallback));client.dispatcher()返回的是Dispatcher對(duì)象所以實(shí)際調(diào)用的是Dispatcher的enqueue(),那么咱們進(jìn)入源碼看下

  //Dispatcher.java
  private int maxRequests = 64;
  private int maxRequestsPerHost = 5;

  synchronized void enqueue(AsyncCall call) {
  //如果正在執(zhí)行的請(qǐng)求小于設(shè)定值即64,并且請(qǐng)求同一個(gè)主機(jī)的request小于設(shè)定值即5
    if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
      //添加到執(zhí)行隊(duì)列,開始執(zhí)行請(qǐng)求
      runningAsyncCalls.add(call);
      //獲得當(dāng)前線程池,沒有則創(chuàng)建一個(gè)
      executorService().execute(call);
    } else {
      //添加到等待隊(duì)列中
      readyAsyncCalls.add(call);
    }
  }

根據(jù)源碼和注釋大家可以看到如果正在執(zhí)行的異步請(qǐng)求小于64,并且請(qǐng)求同一個(gè)主機(jī)小于5的時(shí)候就先往正在運(yùn)行的隊(duì)列里面添加這個(gè)call,然后用線程池去執(zhí)行這個(gè)call,否則就把他放到等待隊(duì)列里面。執(zhí)行這個(gè)call的時(shí)候,自然會(huì)去走到這個(gè)call的run方法,那么咱們看下AsyncCall.java這個(gè)類,而AsyncCall.java又繼承自NamedRunnable.java咱們就一起看下他們的源碼

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();
}

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 {
          responseCallback.onFailure(RealCall.this, e);
        }
      } finally {
        client.dispatcher().finished(this);
      }
    }
  }

上面看到NamedRunnable的構(gòu)造方法設(shè)置了name在的run方法里面設(shè)定為當(dāng)前線程的name,而NamedRunnable的run方法里面調(diào)用了它自己的抽象方法execute,由此可見NamedRunnable的作用就是設(shè)置了線程的name,然后回調(diào)子類的execute方法,那么我們來看下AsyncCall的execute方法。貌似好像又回到了之前同步的getResponseWithInterceptorChain()里面,根據(jù)返回的response來這只callback回調(diào)。所以我們得到了OKHTTP的大體流程,如下圖:

OKHTTP大體流程.png

三、OKHTTP類詳解

大體核心類主要下圖:


核心類.png

最后給大家看一下整體的流程圖

流程.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,739評(píng)論 6 534
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,634評(píng)論 3 419
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 176,653評(píng)論 0 377
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,063評(píng)論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,835評(píng)論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,235評(píng)論 1 324
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,315評(píng)論 3 442
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,459評(píng)論 0 289
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,000評(píng)論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,819評(píng)論 3 355
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,004評(píng)論 1 370
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,560評(píng)論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,257評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,676評(píng)論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,937評(píng)論 1 288
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,717評(píng)論 3 393
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,003評(píng)論 2 374

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