参考:
源码版本:3.14.9
源码地址:https://github.com/square/okhttp
此篇文章主要讲解OkHttp的请求过程,以及源码中一些比较难懂的知识点的使用,并把这些知识点抽取成一个Demo,可以比较深刻的去理解源码的执行过程。Demo 包含 :
- 源码中 Dispatcher类的调度过程
- 以及RealCall类中getResponseWithInterceptorChain()方法中责任链模式的调度过程。
简单调用
String url = "www.baidu.com";
OkHttpClient client = new OkHttpClient.Builder().build();
Request request = new Request.Builder().url(url).build();
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 {
}
});
源码解析流程
此处不讲解OkHttpClient的初始化过程,以及Request的构建过程,用到的是 Builder设计模式,直接从enqueue()方法开始解析。
1. 请求发送过程
- 注意:call.execute()是同步方法,call.enqueue()是异步方法,一般调用call.enqueue()
点击查看call.enqueue()方法,进入到 RealCall类中的call.enqueue()方法,如下:
@Override public void enqueue(Callback responseCallback) {
synchronized (this) {
if (executed) throw new IllegalStateException("Already Executed");
executed = true;
}
transmitter.callStart();
client.dispatcher().enqueue(new AsyncCall(responseCallback));
}
这个 RealCall里面执行的方法,首先会把这个Call加入到Dispatcher这个调度器里面,进入Dispatcher类中的 enqueue() 方法,如下:
void enqueue(AsyncCall call) {
synchronized (this) {
//将此次请求加入准备请求队列中
readyAsyncCalls.add(call);
// Mutate the AsyncCall so that it shares the AtomicInteger of an existing running call to
// the same host.
if (!call.get().forWebSocket) {
AsyncCall existingCall = findExistingCallWithHost(call.host());
if (existingCall != null) call.reuseCallsPerHostFrom(existingCall);
}
}
promoteAndExecute();
}
在Dispatcher类中包含了三个队列,一个线程池:
为了管理所有的请求,Dispatcher采用了队列+生产+消费的模式。
- 为同步执行提供了runningSyncCalls来管理所有的同步请求;
- 为异步执行提供了runningAsyncCalls和readyAsyncCalls来管理所有的异步请求。其中readyAsyncCalls是在当前可用资源不足时,用于缓存请求的。
- ExecutorService线程池
查看 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();
executableCalls.add(asyncCall);
runningAsyncCalls.add(asyncCall);
}
isRunning = runningCallsCount() > 0;
}
for (int i = 0, size = executableCalls.size(); i < size; i++) {
AsyncCall asyncCall = executableCalls.get(i);
//调用 AsyncCall 类 executeOn的方法,在executeOn方法中开启线程池
asyncCall.executeOn(executorService());//1
}
return isRunning;
}
在1处会调用AsyncCall中的executeOn()方法
void executeOn(ExecutorService executorService) {
assert (!Thread.holdsLock(client.dispatcher()));
boolean success = false;
try {
executorService.execute(this);//开启线程池
success = true;
} catch (RejectedExecutionException e) {
InterruptedIOException ioException = new InterruptedIOException("executor rejected");
ioException.initCause(e);
transmitter.noMoreExchanges(ioException);
responseCallback.onFailure(RealCall.this, ioException);
} finally {
if (!success) {
client.dispatcher().finished(this); // This call is no longer running!
}
}
}
此时会调用AsyncCall中的execute()方法,
@Override protected void execute() {
boolean signalledCallback = false;
transmitter.timeoutEnter();
try {
//核心函数
Response response = getResponseWithInterceptorChain();
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);
}
} catch (Throwable t) {
cancel();
if (!signalledCallback) {
IOException canceledException = new IOException("canceled due to " + t);
canceledException.addSuppressed(t);
responseCallback.onFailure(RealCall.this, canceledException);
}
throw t;
} finally {
client.dispatcher().finished(this);
}
}
}
getResponseWithInterceptorChain()方法就是执行拦截器链,直到返回 Response。通过责任链模式循环调用所有拦截器,每个拦截器可以根据Request和Reponse前后执行相应的逻辑。
Response getResponseWithInterceptorChain() throws IOException {
// Build a full stack of interceptors.
List<Interceptor> interceptors = new ArrayList<>();
interceptors.addAll(client.interceptors());
interceptors.add(new RetryAndFollowUpInterceptor(client));
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, transmitter, null, 0,
originalRequest, this, client.connectTimeoutMillis(),
client.readTimeoutMillis(), client.writeTimeoutMillis());
boolean calledNoMoreExchanges = false;
try {
Response response = chain.proceed(originalRequest);
if (transmitter.isCanceled()) {
closeQuietly(response);
throw new IOException("Canceled");
}
return response;
} catch (IOException e) {
calledNoMoreExchanges = true;
throw transmitter.noMoreExchanges(e);
} finally {
if (!calledNoMoreExchanges) {
transmitter.noMoreExchanges(null);
}
}
}
这里把自定义的拦截器,还有内置的必要的拦截器都添加到一个List里面了,最后用List的拦截器创建一个拦截器的链—— RealInterceptorChain。而这个RealInterceptorChain 其实是实现了Interceptor 里面的一个Chain 接口。
我们先了解一下RealInterceptorChain 这个类是如何进行工作的。
首先RealInterceptorChain,是实现了Interceptor.Chain 接口的一个类,这个接口有是三个方法,后面会介绍到,其中一个就是前面调用的proceed方法。
public Response proceed(Request request, Transmitter transmitter, @Nullable Exchange exchange)
throws IOException {
...
// Call the next interceptor in the chain.
RealInterceptorChain next = new RealInterceptorChain(interceptors, transmitter, exchange,
index + 1, request, call, connectTimeout, readTimeout, writeTimeout);
Interceptor interceptor = interceptors.get(index);
Response response = interceptor.intercept(next);
return response;
}
省略了前后的一些代码,发现,其实这里又新建一个 RealInterceptorChain,然后调用了这个拦截器的 intercept 的方法。那么在每个拦截器里面做了什么,这个拦截的方法又是做了什么呢?
首先看一下拦截器这个接口:
public interface Interceptor {
Response intercept(Chain chain) throws IOException;
interface Chain {
Request request();
Response proceed(Request request) throws IOException;
...
}
}
很明显,每个实现Interceptor的拦截器。都会实现了intercept,这样一个拦截的方法。而传入的就是一个Chain。符合前面RealInterceptorChain的调用。
以一个拦截器的代码为例:BridgeInterceptor,这个类实现的intercept方法,而这个方法里面,除了那些前置或后续的操作之外,在中间你会发现 下面一句代码:
Response networkResponse = chain.proceed(requestBuilder.build());
又通过传进来的Chain ,重新调用了proceed的方法。好吧,到这里应该可以了解到这些拦截器,是如何一个个调用被调用的了,原理都是通过了中间的一个RealInterceptorChain,一个接一个的向下调用。然后得到的结果又一个一个向上传。
总结一下,这些拦截器的调用:
刚开始getResponseWithInterceptorChain的最后开始调用了 chain.proceed,然后在RealInterceptorChain的里面,又新建一个 RealInterceptorChain,并且调用当前的拦截器的 intercept,并且把新建的Chain传递进去,然后拦截器的 intercept方法里面,除了一些自身的操作外,又调用Chain的proceed方法。就这样一直调用新建Chian, 一直调用到最后一个拦截器。
这里的调用其实是一个迭代,递归的结构。请求做了前一步的处理才能到下一级,一级级下去,到最后真正发出去请求,相对做了拦截。而得到结果,只有当最后一个拦截器完全了请求,拿到结果之后,才会把结果往上一级,上一级拿到结果,做了相应的处理之后,再到上一级,这就是对结果的拦截处理。
Demo
结构:
调用:
public static void main(String[] args) throws IOException {
//Dispatcher类的调度过程
new Dispatcher().enqueue(new AsyncCall("22","33"));
//demo02调用RealCall类中getResponseWithInterceptorChain()
//方法中责任链模式的调度过程
Request request = new Request();
List<Interceptor> interceptors = new ArrayList<>();
interceptors.add(new RetryAndFollowUpInterceptor());
interceptors.add(new BridgeInterceptor());
interceptors.add(new CacheInterceptor());
interceptors.add(new ConnectInterceptor());
Interceptor.Chain chain = new RealInterceptorChain(interceptors,0,request);
Response response = chain.proceed(request);
}
运行结果:
---Dispatcher---enqueue-
--AsyncCall执行execute方法--
1.失败重试拦截器
2.请求和响应转换拦截器
3.缓存拦截器
4.与服务器建立连接拦截器
RealInterceptorChain 第 3 次执行
RealInterceptorChain 第 2 次执行
RealInterceptorChain 第 1 次执行
RealInterceptorChain 第 0 次执行
Demo挺简单的,可以自行下载:
https://github.com/Ityang/OKHttpDemo