基本用法
同步:
OkHttpClient client = new OkHttpClient.Builder().build();
Request request = new Request.Builder().url("http://www.csdn.net").build();
try {
client.newCall(request).execute();
} catch (IOException e) {
e.printStackTrace();
}
异步:
OkHttpClient client = new OkHttpClient.Builder().dispatcher(dispatcher).build();
Request request = new Request.Builder().url("http://www.csdn.net").build();
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) throws IOException {
}
});
同步流程分析
execute执行的的是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);
}
}
关键方法是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);
return chain.proceed(originalRequest);
}
这里是责任链模式,生成了一个调用链,这里先看一下责任链是怎么进行调用的,再看每个Interceptor的作用
责任链
RealInterceptorChain的processed方法如下(省略非关键代码)
public Response proceed(Request request, StreamAllocation streamAllocation, HttpCodec httpCodec,
...
// 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);
...
return response;
}
这里先为index + 1以后的Interceptor生成一个新的责任链,然后调用第index个Interceptor,Interceptor.intercept方法一般如下
@Override
public Response intercept(Chain chain) throws IOException {
// 做前置处理
Response response = chain.proceed(requestBuilder.build());
// 做后置处理
return response;
}
这里的入参chain就是刚刚生成的index + 1的责任链RealInterceptorChain,这里Interceptor调用proceed开启责任链的下一步,在调用前后可以做前/后置处理。举个例子,如果责任链上有ABC三个节点,那么实际的调用顺序是:
A前置 -> B前置 -> C -> B后置 -> A后置。
okHttp各Interceptor功能简述
在getResponseWithInterceptorChain中有一下一个调用链
- client.interceptors(),调用者自定义的Interceptor
- RetryAndFollowUpInterceptor,重试以及部分HTTP status code的处理
- BridgeInterceptor,对request和response的头做一些公共处理
- CacheInterceptor,请求的缓存
- ConnectInterceptor,进行连接
- client.networkInterceptors(),调用者自定义的另一些Interceptor
- CallServerInterceptor,用上面生成的链接发起请求
各个Interceptor的实现后续再详细分析
清理工作
RealCall.execute方法的最后会调用dispatcher的finish方法
/** Used by {@code Call#execute} to signal completion. */
void finished(RealCall call) {
finished(runningSyncCalls, call, false);
}
private <T> void finished(Deque<T> calls, T call, boolean promoteCalls) {
int runningCallsCount;
Runnable idleCallback;
synchronized (this) {
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();
}
}
这里做的清理工作比较简单,就是把RealCall从dispatcher的runningSyncCalls中remove掉,如果调用者自定义的idleCallback,会调用它。promoteCalls里处理的是异步调用,这里因为入参promoteCalls是false,所以不会调用到
异步调用
RealCall.enqueue
@Override public void enqueue(Callback responseCallback) {
synchronized (this) {
if (executed) throw new IllegalStateException("Already Executed");
executed = true;
}
captureCallStackTrace();
client.dispatcher().enqueue(new AsyncCall(responseCallback));
}
Dispatcher.enqueue
synchronized void enqueue(AsyncCall call) {
if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
runningAsyncCalls.add(call);
executorService().execute(call);
} else {
readyAsyncCalls.add(call);
}
}
如果已经正在执行的异步任务达到上限,就加入到异步准备队列,否则放到线程池中执行。执行的话,会调用到AsyncCall.execute,这里跟同步任务几乎一样,不再分析。如果是放到准备队列里的话,在一个异步任务执行完毕进行清理的时候,会调用finish,这里传入的promoteCalls是true
/** Used by {@code AsyncCall#run} to signal completion. */
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) {
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();
}
}
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.
}
}
因此,会调用到promoteCalls()方法,尝试进行准备队列里异步任务的执行。
基本流程就到此结束了,详细分析见后续