基本使用
-
異步GET
Request.Builder builder = new Request.Builder().url("https://www.baidu.com/"); builder.method("GET",null); Request build = builder.build(); OkHttpClient client = new OkHttpClient(); Call call = client.newCall(build); call.enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { } @Override public void onResponse(Call call, Response response) throws IOException { System.out.println(response.body().string()); } }); -
異步POST
FormBody.Builder builder = new FormBody.Builder().add("XXX", "XXX"); FormBody build = builder.build(); Request request = new Request.Builder().url("https://.........").post(build).build(); OkHttpClient client = new OkHttpClient(); Call call = client.newCall(request); call.enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { } @Override public void onResponse(Call call, Response response) throws IOException { System.out.println(response.body().string()); } });
用法都非常簡單,只用簡單的調(diào)用一下,就能實現(xiàn)所想需要實現(xiàn)的GET,POST請求。
源碼分析
我們還是從請求處理開始分析起:
Call call = client.newCall(request);
我們通常就會這樣聲明一個 Call 對象 然后執(zhí)行異步 enqueue() 或者同步 execute()方法。
點進 newCall 里面:
@Override public Call newCall(Request request) {
return RealCall.newRealCall(this, request, false /* for web socket */);
}
這里實際就是返回了 RealCall 這個對象, 而接下來 網(wǎng)絡(luò)請求 實際上就是調(diào)用 RealCall 的里面的方法。
分析 -- 異步enqueue()
@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));
}
從上面可以得知請求是從 dispatcher 完成的。
接下來分析 dispatcher
在 Dispatcher.java 下
先看看這個類所定義的變量吧
最大并發(fā)請求數(shù)
private int maxRequests = 64;
每個主機最大的請求數(shù)
private int maxRequestsPerHost = 5;
/** 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<>();
由此可以看出他維護個各種隊列,把不同的Call放置相對應(yīng)的隊列中去,隊列中的請求最后會一個個的進行訪問。
接下來看看構(gòu)造函數(shù)
/** Executes calls. Created lazily. */
private @Nullable ExecutorService executorService;
public Dispatcher(ExecutorService executorService) {
this.executorService = executorService;
}
public Dispatcher() {
}
構(gòu)造函數(shù)有兩個,一個構(gòu)造函數(shù)是帶參的,這個參數(shù)就是自己實現(xiàn)的線程池,如果我們調(diào)用不帶參的構(gòu)造函數(shù)時,executorService沒有被初始化。而為他初始化的方法是 executorService () .
public synchronized ExecutorService executorService() {
if (executorService == null) {
executorService = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>(), Util.threadFactory("OkHttp Dispatcher", false));
}
return executorService;
}
從上面看到他會創(chuàng)建一個默認的線程池 。
那么接下來在異步請求的時候會調(diào)用enqueue() 方法 ,而從下面我們可以看到 當異步請求隊列 數(shù)量小于 64 并且正在運行的請求主機數(shù)小于5時,會把請求放置在 runningAsyncCalls 中 并在線程池中執(zhí)行。 否則就加入到 readyAsyncCalls 中進行緩存。
synchronized void enqueue(AsyncCall call) {
if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
runningAsyncCalls.add(call);
executorService().execute(call);
} else {
readyAsyncCalls.add(call);
}
}
然后就會執(zhí)行以下方法
executorService().execute(call);
executorService()會返回一個線程池 , 如果使用的是默認線程池的話:那么在 ThreadPoolExecutor 內(nèi) ,所要傳進去的是 Runnable 這個接口,
public void execute(Runnable command) {
.....
}
再看看 AsyncCall 這個類吧 :
AsyncCall 是 RealCall 的 內(nèi)部類 。 他繼承了NamedRunnable,而NamedRunnable正是實現(xiàn)了Runnable方法。
在NamedRunnable里面實現(xiàn)了run() 方法 ,run() 里面調(diào)用了他的一個 抽象方法 :
protected abstract void execute();
那么子類就只要實現(xiàn) execute 方法就可以了:
所以就回到了 AsyncCall 中實現(xiàn)的 execute() 方法
@Override protected void execute() {
try{
......
} finally {
client.dispatcher().finished(this);
}
}
先來看看這個方法最后都做了什么吧 :
無論如何都會調(diào)用到 client.dispatcher().finished(this); 這個方法
進去 finished 方法 ,我們看到最后調(diào)用的方法為以下:
void finished(AsyncCall call) {
finished(runningAsyncCalls, call, true);
}
private <T> void finished(Deque<T> calls, T call, boolean promoteCalls) {
int runningCallsCount;
Runnable idleCallback;
synchronized (this) {
注 1
if (!calls.remove(call)) throw new AssertionError("Call wasn't in-flight!");
if (promoteCalls) promoteCalls();
runningCallsCount = runningCallsCount();
idleCallback = this.idleCallback;
}
if (runningCallsCount == 0 && idleCallback != null) {
idleCallback.run();
}
}
從上面可以看到 calls 是 runningAsyncCalls ,首先他先從隊列移除,然后執(zhí)行
promoteCalls() ,隨后將更新 runningCallsCount 和 idleCallback 。
主要的方法就是 promoteCalls()
private void promoteCalls() {
if (runningAsyncCalls.size() >= maxRequests) return; // Already running max capacity.
if (readyAsyncCalls.isEmpty()) return; // No ready calls to promote.
for (Iterator<AsyncCall> i = readyAsyncCalls.iterator(); i.hasNext(); ) {
AsyncCall call = i.next();
if (runningCallsForHost(call) < maxRequestsPerHost) {
i.remove();
runningAsyncCalls.add(call);
executorService().execute(call);
}
if (runningAsyncCalls.size() >= maxRequests) return; // Reached max capacity.
}
}
從for語句可以明顯看出 因為 runningAsyncCalls 的請求被移除了 , 那么就會從 readyAsyncCalls 中拿出請求向 runningAsyncCalls 補充 。
接著我們回到 execute() 方法 ,看看其中實現(xiàn)了什么:
@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);
}
}
從名字可以看出 Response 就是請求的結(jié)果, 而網(wǎng)絡(luò)請求交給了
getResponseWithInterceptorChain()
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);
}
構(gòu)建了一大堆攔截器,最后 創(chuàng)建了 RealInterceptorChain 這個 對象,他實際作用就是一個 攔截鏈 。
最后把請求交給了攔截鏈的proceed () 方法:
@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 {
.....
注 1
RealInterceptorChain next = new RealInterceptorChain(interceptors, streamAllocation, httpCodec,
connection, index + 1, request, call, eventListener, connectTimeout, readTimeout,
writeTimeout);
Interceptor interceptor = interceptors.get(index);
Response response = interceptor.intercept(next);
.....
return response;
}
注 1 : 從上面可以看出了這個攔截鏈會不斷的調(diào)用下一個攔截器。從而現(xiàn)在分析一下所添加的攔截器吧。
在getResponseWithInterceptorChain() 方法中,里面就是添加了一堆攔截器
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));
在拿取攔截鏈里面的攔截器,然后一一執(zhí)行。
retryAndFollowUpInterceptor -- 這攔截器主要是做重試,網(wǎng)絡(luò)錯誤,以及請求重定向的一些操作。
BridgeInterceptor -- 這個攔截器,主要把用戶的請求轉(zhuǎn)換為網(wǎng)絡(luò)的請求,負責對Request和Response報文進行加工。
CacheInterceptor -- 緩存攔截器
ConnectInterceptor -- 連接攔截器,主要是處理連接服務(wù)器,以及http , https的包裝
CallServerInterceptor -- 服務(wù)攔截器,主要是發(fā)送(write、input)、讀?。╮ead、output)數(shù)據(jù)。也是攔截器的最后一個環(huán)節(jié),這里就真正拿到了網(wǎng)絡(luò)的結(jié)果了。
攔截器會不斷的調(diào)用下一個攔截器,最后全部執(zhí)行完。在每個攔截器里面,你可以看到類似的代碼 : Response networkResponse = chain.proceed(...); 這就是調(diào)用了下一個攔截器。
攔截器所要執(zhí)行的內(nèi)容基本就如上的簡述了。