Duchen's Blog

OkHttp源码分析

异步请求流程

  • 从这样一句话开始发出一个异步的请求

okHttpClient.newCall(request).enqueue(callback);

  • 实际上调用的是 RealCall 的 enqueue 方法,将回调包装成一个 AsyncCall(NamedRunnabled的子类) 传递给了 Client 的 Dispatcher
1
2
3
4
5
6
7
8
9
10
11
12
13
//@see OkHttpClient
@Override public Call newCall(Request request) {
return new RealCall(this, request);
}
//@see RealCall
@Override public void enqueue(Callback responseCallback) {
synchronized (this) {
if (executed) throw new IllegalStateException("Already Executed");
executed = true;
}
client.dispatcher().enqueue(new AsyncCall(responseCallback));
}
  • 每当 Dispatcher 收到一个新的 AsyncCall
    1. 如果有空闲的线程就去将其放入执行队列,并执行它
    2. 没有的话,就放入等待队列
1
2
3
4
5
6
7
8
9
//@see Dispatcher
synchronized void enqueue(AsyncCall call) {
if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
runningAsyncCalls.add(call);
executorService().execute(call);
} else {
readyAsyncCalls.add(call);
}
}
  • AsyncCall 的执行过程通过 getResponseWithInterceptorChain() 来链式调用client.interceptors(),从上到下层层包装了各种缓存、重试等机制,并添加部分默认的Headers参数等,最后调用到CallServerInterceptor.intercept(Chain chain)方法和服务器建立 Socket 连接取得 Response,然后再把 Response 沿着来时的顺序由下往上层层返回,并进行相应的处理,最后返回到 AsyncCall 的 execute 方法中。

  • 然后相应的调用成功或失败的回调(还是在执行线程中,不会切换到主线程)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
//@see RealCall.AsyncCall
@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);
}
}
private 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 (!retryAndFollowUpInterceptor.isForWebSocket()) {
interceptors.addAll(client.networkInterceptors());
}
interceptors.add(new CallServerInterceptor(
retryAndFollowUpInterceptor.isForWebSocket()));
Interceptor.Chain chain = new RealInterceptorChain(
interceptors, null, null, null, 0, originalRequest);
return chain.proceed(originalRequest);
}
  • 最后在client.dispatcher().finished()方法中会
    1. 将该 AsyncCall 从执行队列中移除
    2. 调用Dispatcher.promoteCalls()方法来将等待队列中的 AsyncCall 放入执行队列中并执行
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//@see Dispatcher
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.
}
}

同步请求流程

这个会把 realCall 放到 dispatcher 的 runningSyncCalls 中,用于对请求的统一管理

并直接在当前线程调用getResponseWithInterceptorChain()获得 Response

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//@see RealCall
@Override public Response execute() throws IOException {
synchronized (this) {
if (executed) throw new IllegalStateException("Already Executed");
executed = true;
}
try {
client.dispatcher().executed(this);
Response result = getResponseWithInterceptorChain();
if (result == null) throw new IOException("Canceled");
return result;
} finally {
client.dispatcher().finished(this);
}
}