OkHttp 源碼分析

OkHttp 源碼分析java

基於OkHttp3.11.0web

implementation("com.squareup.okhttp3:okhttp:3.11.0")

網絡框架的核心思想都是構建基本的執行單元以後(1),根據任務類型放入對應的任務隊列裏(2),再由線程池去執行(3)。OKHttp也不列外。緩存

初始化OKHttpClient

OKHttpclient採用了Builder模式建立cookie

OkHttpClient okHttpClient = new OkHttpClient.Builder()
        .connectTimeout(10, TimeUnit.SECONDS)
        .readTimeout(5, TimeUnit.SECONDS)
        .writeTimeout(5, TimeUnit.SECONDS)
        .build();

構建執行單元

1:GET請求

Request request = new Request.Builder().url("www.baidu.com")
        .get() // 默認就是get請求
        .build();

2: POST請求

POST與GET多了一個body。網絡

FormBody body = new FormBody.Builder()
        .add("key", "value")
        .add("key1", "value1")
        .build();

Request post = new Request.Builder().url("www.baidu.com")
        .post(body)
        .build();

執行

1:同步執行

try {
    Response response = okHttpClient.newCall(post).execute();
    if (response.code() ==  200){
          }

} catch (IOException e) {

}

而後就能夠根據response的結果操做了。框架

2:異步執行

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

    @Override
    public void onResponse(Call call, Response response) throws IOException {

    }
});

在對應的回調函數裏作對應的業務邏輯。異步

以上就是OKHttp的使用的基本使用。socket

這裏Request就是請求單元,不管是同步執行仍是異步執行,都調用okHttpClient.newCall(request) 生成了一個RealCall對象,而後分別調用該對象的execute(同步執行)方法或者enqueue(異步執行)方法。async

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

OKHttp的newCall方法調用RealCall的靜態方法newRealCall().ide

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;
}
private RealCall(OkHttpClient client, Request originalRequest, boolean forWebSocket) {
  this.client = client;
  this.originalRequest = originalRequest;
  this.forWebSocket = forWebSocket;
  this.retryAndFollowUpInterceptor = new RetryAndFollowUpInterceptor(client, forWebSocket);
}

能夠看到,newRealCall方法將client做爲本身構造函數的參數傳入

下面這個方法是RealCall對象的execute方法

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

能夠看到調用了 client.dispatcher().executed(this);

最中調用 Response result = getResponseWithInterceptorChain();並返回Result對象

若是發生了異常則調用 eventListener.callFailed(this, e);

而最終這會調用 client.dispatcher().finished(this),來結束這個call。

這裏面有一個很重要的類Dispatcher,它是OKHttpclient的一個內部成員,同時OKHttpclient是request的內部成員

public final class Dispatcher {
      private int maxRequests = 64;  //最大的請求數量
      private int maxRequestsPerHost = 5; //同義主機同時支持的最大請求數
      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<>(); //正在運行的同步任務隊列
  
  }

分別看到,這個類的同步執行方法是

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

將改call假如同步執行隊列中。

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

異步執行方法是先進行判斷,只有正在執行的異步任務隊列長度小於了最大的請求數而且改請求的主機的正在請求數量小於每一個主句的同時的最大鏈接數世纔將改請求加入到正在執行的異步任務隊列裏,而後由具體的執行任務來執行這個請求任務。

否則就把這個任務加入到待執行的異步執行隊隊列。

這裏RealCall 對象忽然就變成了一個AsyncCall對象

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

在RealCall執行enqueue方法時將一個回調對象做爲構造參數生成了一個AsyncCall對象,傳入了Dispatcher的enqueue方法。

final class AsyncCall extends NamedRunnable {
      private final Callback responseCallback;

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

Async對象其實繼承了NamedRunnable。而NamedRunnable實現了Runnable接口,能夠看出其實Async其實就是一個命名後的runnable對象。

這裏把RealCall同步執行和異步執行的代碼列出來

1:同步執行

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

2:異步執行

最終調用AsyncCall對象的execute方法

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

能夠看出無論是同步執行仍是異步執行,最終都是調用getResponseWithInterceptorChain();

方法得出Response

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

在這個方法裏首先將用戶添加到OKHttpClient上的應用攔截器添加到攔截器列表裏。而後一次添加劇試重定向攔截器, 頭部信息處理攔截器,緩存攔截器, 鏈接攔截器,而後再加上OKhttpclient配置的網絡攔截器,最後添加最終發起請求的攔截器。

攔截器這裏使用了不完整的責任鏈模式,依次處理返回的response,最後返回最終的response。

相關文章
相關標籤/搜索