OkHttp3 源碼閱讀

版本是3.14.9

同步請求

OkHttpClient okHttpClient = new OkHttpClient();
Request request = new Request.Builder().url("http://wwww.baidu.com").build();
Call call = okHttpClient.newCall(request);
try {
    Response response = call.execute();
    Log.d(TAG, "Response: " + response.body().string());
} catch (IOException e) {
    e.printStackTrace();
}

同步請求分析

  1. 創建OkHttpClient對象,
public class OkHttpClient implements Cloneable, Call.Factory, WebSocket.Factory {
    public OkHttpClient() {
      this(new Builder());
    }
    public static final class Builder {
        Dispatcher dispatcher;
        public Builder() {
            // 創建Dispatcher對象
            dispatcher = new Dispatcher();
        }
    }
}
  1. 創建Request對象
public final class Request {
    public static class Builder {
        public Builder() {
          this.method = "GET";
          this.headers = new Headers.Builder();
        }
        public Builder url(HttpUrl url) {
          if (url == null) throw new NullPointerException("url == null");
          this.url = url;
          return this;
        }
        public Request build() {
          if (url == null) throw new IllegalStateException("url == null");
          // build()之後返回Request
          return new Request(this);
        }
    }
}
  1. okHttpClient.newCall(request)創建RealCall對象
// 創建RealCall對象, RealCall中的內部類AsyncCall其實是Runnable對象
@Override public Call newCall(Request request) {
  return RealCall.newRealCall(this, request, false /* for web socket */);
}
  1. RealCall.execute()執行請求
// RealCall.java
final class RealCall implements Call {
    // 執行同步請求
    @Override public Response execute() throws IOException {
      synchronized (this) {
        // executed 每個RealCall只能請求一次網絡
        if (executed) throw new IllegalStateException("Already Executed");
        executed = true;
      }
      ...
      try {
        // 將RealCall加入到同步請求的隊列中
        client.dispatcher().executed(this);
        // 從攔截鏈獲取響應, 異步最終也會走到這個方法,現在再分析異步.
        return getResponseWithInterceptorChain();
      } finally {
        client.dispatcher().finished(this);
      }
    }
}
// Dispatcher.java
public final class Dispatcher {
      // 準備好,還未請求
      private final Deque<AsyncCall> readyAsyncCalls = new ArrayDeque<>();
      // 正在運行的請求
      private final Deque<AsyncCall> runningAsyncCalls = new ArrayDeque<>();
      // 同步請求  
      private final Deque<RealCall> runningSyncCalls = new ArrayDeque<>();
      // 將RealCall對象加入到同步請求隊列中
      synchronized void executed(RealCall call) {
        runningSyncCalls.add(call);
      }
}

異步請求

OkHttpClient okHttpClient = new OkHttpClient();
Request request = new Request.Builder().url("http://wwww.baidu.com").build();
Call call = okHttpClient.newCall(request);
call.enqueue(new Callback() {
    @Override
    public void onFailure(Call call, IOException e) {
        Log.d(TAG, "onFailure: ");
    }
    @Override
    public void onResponse(Call call, Response response) throws IOException {
        Log.d(TAG, "Response: " + response.body().string());
    }
});

異步請求分析

  1. OkHttpClient,Request,RealCall對象的創建與同步無異,區別在RealCall.execute()與’RealCall.enqueue()’
final class RealCall implements Call {
    @Override public void enqueue(Callback responseCallback) {
      ... 
      client.dispatcher().enqueue(new AsyncCall(responseCallback));
    }
    // 類型最終爲Runnable
    final class AsyncCall extends NamedRunnable {
        void executeOn(ExecutorService executorService) {
          assert (!Thread.holdsLock(client.dispatcher()));
          boolean success = false;
          try {
            // 通過線程池執行當前的AsyncCall,也就是Runnable對象中的run()
            // NamedRunnable類中的run()方法最終調用execute(),該方法具體由AsyncCall實現.
            executorService.execute(this);
            success = true;
          }
          ...
        }
        // run()方法的最終實現
        @Override protected void execute() {
          boolean signalledCallback = false;
          transmitter.timeoutEnter();
          try {
            // 調用攔截器鏈獲取Response
            Response response = getResponseWithInterceptorChain();
            signalledCallback = true;
            // Callback()中的回調方法 
            responseCallback.onResponse(RealCall.this, response);
          } catch (IOException e) {
            ...
          } catch (Throwable t) {
            cancel();
            if (!signalledCallback) {
              ...
              canceledException.addSuppressed(t);
              // Callback()中的回調方法 
              responseCallback.onFailure(RealCall.this, canceledException);
            }
            throw t;
          } finally {
            client.dispatcher().finished(this);
          }
        }
    }

}
public final class Dispatcher {
    private int maxRequests = 64;
    private int maxRequestsPerHost = 5;
    // 準備好,還未請求
    private final Deque<AsyncCall> readyAsyncCalls = new ArrayDeque<>();
    // 正在運行的請求
    private final Deque<AsyncCall> runningAsyncCalls = new ArrayDeque<>();
    // 同步請求  
    private final Deque<RealCall> runningSyncCalls = new ArrayDeque<>();
    // 將RealCall對象加入到同步請求隊列中
    synchronized void executed(RealCall call) {
      runningSyncCalls.add(call);
    }

    void enqueue(AsyncCall call) {
      // 將AsyncCall對象加入異步請求準備隊列中
      readyAsyncCalls.add(call);
      ...
      // 
      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(); ) {
          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();
          // 將等待隊列中的AsyncCall 加入到正在異步請求的隊列中
          executableCalls.add(asyncCall);
          runningAsyncCalls.add(asyncCall);
        }
        isRunning = runningCallsCount() > 0;
      }
      for (int i = 0, size = executableCalls.size(); i < size; i++) {
        // 從集合中取出AsyncCall
        AsyncCall asyncCall = executableCalls.get(i);
        // 調用AsyncCall中的executeOn()方法,executorService()返回一個線程池
        asyncCall.executeOn(executorService());
      }
      return isRunning;
    }
    // 獲取一個線程池
    public synchronized ExecutorService executorService() {
      if (executorService == null) {
        // 核心池大小爲0,空閒線程最多等待60s收回
        executorService = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60, TimeUnit.SECONDS,
            new SynchronousQueue<>(), Util.threadFactory("OkHttp Dispatcher", false));
      }
      return executorService;
    }
}

getResponseWithInterceptorChain()

final class RealCall implements Call {
    final class AsyncCall extends NamedRunnable {
        
        Response getResponseWithInterceptorChain() throws IOException {
          // Build a full stack of interceptors.
          List<Interceptor> interceptors = new ArrayList<>();
          // OkHttpClient中自己自定義的一些Interceptor
          interceptors.addAll(client.interceptors());
          // 錯誤、重定向攔截器
          interceptors.add(new RetryAndFollowUpInterceptor(client));
          // 橋接攔截器,橋接應用層與網絡層,添加必要的頭、  
          interceptors.add(new BridgeInterceptor(client.cookieJar()));
          // 緩存處理,Last-Modified、ETag、DiskLruCache等  
          interceptors.add(new CacheInterceptor(client.internalCache()));
          // 連接攔截器  
          interceptors.add(new ConnectInterceptor(client));
          if (!forWebSocket) {
            // 網絡請求攔截器只對非網頁請求生效
            interceptors.addAll(client.networkInterceptors());
          }
          // 真正訪問服務器的攔截器
          interceptors.add(new CallServerInterceptor(forWebSocket));
          // 創建RealInterceptorChain對象, 注意此時的index爲0
          Interceptor.Chain chain = new RealInterceptorChain(interceptors, transmitter, null, 0,
              originalRequest, this, client.connectTimeoutMillis(),
              client.readTimeoutMillis(), client.writeTimeoutMillis());
          boolean calledNoMoreExchanges = false;
          try {
            // 調用RealInterceptorChain.proceed() 接收參數是Request
            Response response = chain.proceed(originalRequest);
            ...
            return response;
          } 
          ...
        }
    }
}

RealInterceptorChain.proceed(originalRequest)

public final class RealInterceptorChain implements Interceptor.Chain {
    public Response proceed(Request request, Transmitter transmitter, @Nullable Exchange exchange)
        throws IOException {
      ...
      // 注意此時的index爲index+1,回想之前的一步,創建RealInterceptorChain時候, index是爲0.
      // 可以看出來這裏用的是責任鏈設計模式.  
      // 攔截器鏈最後就是一個遞歸調用, 最後調用到 CallServerInterceptor纔開始真正的請求網絡,然後再一步步將請求到的數據從攔截器返回來. 
      RealInterceptorChain next = new RealInterceptorChain(interceptors, transmitter, exchange,
          index + 1, request, call, connectTimeout, readTimeout, writeTimeout);
      // 上一步中index爲0,那麼這個 Interceptor 類型就是錯誤重定向攔截器
      Interceptor interceptor = interceptors.get(index);
      // 這裏的next還是RealInterceptorChain對象. 下面看下錯誤重定向請求攔截器
      Response response = interceptor.intercept(next);
      ...
      return response;
    }
}

RetryAndFollowUpInterceptor.intercept(next)

public final class RetryAndFollowUpInterceptor implements Interceptor {
    @Override public Response intercept(Chain chain) throws IOException {
      Request request = chain.request();
      RealInterceptorChain realChain = (RealInterceptorChain) chain;
        ...
        try {
          // 這樣一個循環最後又回到了RealInterceptorChain中的proceed()方法中了,此時的RealInterceptorChain中屬性index爲1.
          // 這樣一個循環就會將所有的 Interceptor都調用到. 
          response = realChain.proceed(request, transmitter, null);
          success = true;
        } 
        ...
    }
}

總結

OkHttp的底層是通過Java的Socket發送HTTP請求與接受響應的,OkHttp實現了連接池的概念,即對於同一主機的多個請求,其實可以共用一個Socket連接,而不是每次發送完 HTTP請求就關閉底層的Socket,這樣就實現了連接池的概念。而OkHttp對Socket的讀寫操作使用的OkIo庫進行了一 層封裝。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章