分析版本为 3.0.5
一般app gradle中引用:
compile 'com.squareup.okhttp3:okhttp:3.5.0'
下面根据使用来分析调用的流程,仅限调用的流程!
1.OkHttpClient
Call call = mOkHttpClient.newCall(request);
call.enqueue(new Callback());
通过OkHttpClient调用newCall方法,获取call对象,Call是个interface,实际实现类是Realcall类。
2.Realcall
这个类十分的关键,里面有同步execute请求,异步enqueue请求,同时里面还有个内部类AsyncCall,后面调用的时候再分析
直接看异步请求(同步请求类似,话说你们会用同步的请求吗?)
@Override public void enqueue(Callback responseCallback) {
//省略部分代码
client.dispatcher().enqueue(new AsyncCall(responseCallback));
}
注意,返回类型是void,那么我们的response跑哪里去了呢?先不着急,先看看Dispatcher是什么鬼。
3.Dispatcher
private int maxRequests = 64;//最大请求个数
private int maxRequestsPerHost = 5;//最大主机响应个数
private Runnable idleCallback;
private ExecutorService executorService;//线程池
private final Deque<AsyncCall> readyAsyncCalls = new ArrayDeque<>();//待定异步请求队列
private final Deque<AsyncCall> runningAsyncCalls = new ArrayDeque<>();//正在运行异步请求队列
private final Deque<RealCall> runningSyncCalls = new ArrayDeque<>();//正在运行同步请求队列
继续第二步中的client.dispatcher().enqueue()代码:
synchronized void enqueue(AsyncCall call) {
if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
runningAsyncCalls.add(call);//满足条件加入队列中
executorService().execute(call);//执行
} else {
readyAsyncCalls.add(call);//满足条件加入队列中
}
}
executorServicesh是一个线程池对象,构造方法为:
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;
}
executorService().execute(call);//执行
再次阅读这行代码,大家应该就会明白什么意思了吧。也即执行线程的run方法,call是AsyncCall 我们在步骤一中提到过,是Realcall的内部类,来看看其代码
4.AsyncCall
final class AsyncCall extends NamedRunnable {
//省略部分代码
@Override protected void execute() {
boolean signalledCallback = false;
try {
Response response = getResponseWithInterceptorChain();//重点1
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);//重点2
}
}
}
NamedRunnable继承自Runnable接口,run方法中调用execute方法,所以也即AsyncCall 实现自Runnable,run方法对应execute,步骤3中调用的execute实际调用的就是该类中的execute方法。
好累啊,绕来绕去还是Realcall中的类,但是我们的Dispatch却实现了其多线程的功能了,是不是很赞!
代码中,可以看到Response对象的返回了,也即调用:
5.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);
}
这个方法,主要是为了加一些拦截器,拦截器的概念可以简单理解为:在Response之前和之后可以分别做一些自己的操作,比如最简单的打印log,完全可以用拦截器来实现,interceptors.addAll(client.interceptors())意思为添加我们自定义的拦截器,其他为一些系统定义的拦截器。最后调用RealInterceptorChain的proceed方法。
6.RealInterceptorChain
public Response proceed(Request request, StreamAllocation streamAllocation, HttpCodec httpCodec,
Connection connection) throws IOException {
//省略部分代码
RealInterceptorChain next = new RealInterceptorChain(
interceptors, streamAllocation, httpCodec, connection, index + 1, request);
Interceptor interceptor = interceptors.get(index);
Response response = interceptor.intercept(next);
//省略部分代码
return response;
}
创建一个RealInterceptorChain对象,获取一个Interceptor对象,调用intercept方法,怎么就返回了Response对象了呢?所以还是看看intercept是什么吧。
7.Interceptor
看看其实现类,retryAndFollowUpInterceptor(如果没有自己添加的拦截器,index=0时获取就是该拦截器)
拦截器都是实现自Interceptor,先看看其源码
public interface Interceptor {
Response intercept(Chain chain) throws IOException;
interface Chain {
Request request();
Response proceed(Request request) throws IOException;
Connection connection();
}
}
深入retryAndFollowUpInterceptor的源码的intercept方法你会发现,内部调用chain的proceed方法,原来是循环嵌套调用RealInterceptorChain的proceed方法,一个一个拦截器的intercept的方法调用后,最后调用到CallServerInterceptor的这个拦截器,并且,其intercept方法中实现了网络请求调用,终于找到了!!!
8.CallServerInterceptor
@Override public Response intercept(Chain chain) throws IOException {
HttpCodec httpCodec = ((RealInterceptorChain) chain).httpStream();
StreamAllocation streamAllocation = ((RealInterceptorChain) chain).streamAllocation();
Request request = chain.request();
long sentRequestMillis = System.currentTimeMillis();
httpCodec.writeRequestHeaders(request);
if (HttpMethod.permitsRequestBody(request.method()) && request.body() != null) {
Sink requestBodyOut = httpCodec.createRequestBody(request, request.body().contentLength());
BufferedSink bufferedRequestBody = Okio.buffer(requestBodyOut);
request.body().writeTo(bufferedRequestBody);
bufferedRequestBody.close();
}
httpCodec.finishRequest();
Response response = httpCodec.readResponseHeaders()
.request(request)
.handshake(streamAllocation.connection().handshake())
.sentRequestAtMillis(sentRequestMillis)
.receivedResponseAtMillis(System.currentTimeMillis())
.build();
int code = response.code();
if (forWebSocket && code == 101) {
// Connection is upgrading, but we need to ensure interceptors see a non-null response body.
response = response.newBuilder()
.body(Util.EMPTY_RESPONSE)
.build();
} else {
response = response.newBuilder()
.body(httpCodec.openResponseBody(response))
.build();
}
if ("close".equalsIgnoreCase(response.request().header("Connection"))
|| "close".equalsIgnoreCase(response.header("Connection"))) {
streamAllocation.noNewStreams();
}
if ((code == 204 || code == 205) && response.body().contentLength() > 0) {
throw new ProtocolException(
"HTTP " + code + " had non-zero Content-Length: " + response.body().contentLength());
}
return response;
}
这个方法中,实现最后的网络请求,原来拦截器的功能这么强大呢!