1.构造Demo
首先构造一个简单的异步网络访问Demo:
OkHttpClient client = new OkHttpClient(); Request request = new Request.Builder() .url("http://publicobject.com/helloworld.txt") .build();client.newCall(request).enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { Log.d("OkHttp", "Call Failed:" + e.getMessage()); } @Override public void onResponse(Call call, Response response) throws IOException { Log.d("OkHttp", "Call succeeded:" + response.message()); }});
2. 发起请求
OkHttpClient.newCall
实际是创建一个RealCall
实例:
@Override public Call newCall(Request request) { return new RealCall(this, request, false /* for web socket */);}
RealCall.enqueue
实际就是讲一个RealCall
放入到任务队列中,等待合适的机会执行:
@Override public void enqueue(Callback responseCallback) { synchronized (this) { if (executed) throw new IllegalStateException("Already Executed"); executed = true; } captureCallStackTrace(); client.dispatcher().enqueue(new AsyncCall(responseCallback));}
从代码中可以看到最终RealCall
被转化成一个AsyncCall
并被放入到任务队列中,任务队列中的分发逻辑这里先不说,相关实现会放在疑问进行介绍。这里只需要知道AsyncCall的excute方法最终将会被执行:
[RealCall.java] @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); } } }
execute
方法的逻辑并不复杂,简单的说就是:
- 调用
getResponseWithInterceptorChain
获取服务器返回 - 通知任务分发器(
client.dispatcher
)该任务已结束
getResponseWithInterceptorChain
构建了一个拦截器链,通过依次执行该拦截器链中的每一个拦截器最终得到服务器返回。
3. 构建拦截器链
首先来看下getResponseWithInterceptorChain
的实现:
源码路径:okhttp3/RealCall.java
1 // 开始执行整个请求 2 Response getResponseWithInterceptorChain() throws IOException { 3 // Build a full stack of interceptors. 4 // 拦截器栈 5 Listinterceptors = new ArrayList<>(); 6 // 前文说过的 普通拦截器 7 interceptors.addAll(client.interceptors()); 8 // 重试拦截器,网络错误、请求失败等 9 interceptors.add(retryAndFollowUpInterceptor);10 // 桥接拦截器,主要是重构请求头即header11 interceptors.add(new BridgeInterceptor(client.cookieJar()));12 // 缓存拦截器13 interceptors.add(newCacheInterceptor(client.internalCache()));14 // 连接拦截器,连接服务器,https包装15 interceptors.add(new ConnectInterceptor(client));16 // 网络拦截器,websockt不支持,同样是自定义17 if (!forWebSocket) {18 interceptors.addAll(client.networkInterceptors());19 }20 // 服务拦截器,主要是发送(write、input)、读取(read、output)数据21 interceptors.add(new CallServerInterceptor(forWebSocket));22 23 // 开启调用链24 Interceptor.Chain chain = new RealInterceptorChain(25 interceptors, null, null, null, 0, originalRequest);26 return chain.proceed(originalRequest);27 }
其逻辑大致分为两部分:
- 创建一系列拦截器,并将其放入一个拦截器数组中。这部分拦截器即包括用户自定义的拦截器也包括框架内部拦截器
- 创建一个拦截器链
RealInterceptorChain
,并执行拦截器链的proceed
方法
接下来看下RealInterceptorChain
的实现逻辑:
1 public final class RealInterceptorChain implements Interceptor.Chain { 2 private final Listinterceptors; 3 private final StreamAllocation streamAllocation; 4 private final HttpCodec httpCodec; 5 private final RealConnection connection; 6 private final int index; 7 private final Request request; 8 private int calls; 9 10 public RealInterceptorChain(List interceptors, StreamAllocation streamAllocation,11 HttpCodec httpCodec, RealConnection connection, int index, Request request) {12 this.interceptors = interceptors;13 this.connection = connection;14 this.streamAllocation = streamAllocation;15 this.httpCodec = httpCodec;16 this.index = index;17 this.request = request;18 }19 20 @Override public Connection connection() {21 return connection;22 }23 24 public StreamAllocation streamAllocation() {25 return streamAllocation;26 }27 28 public HttpCodec httpStream() {29 return httpCodec;30 }31 32 @Override public Request request() {33 return request;34 }35 36 @Override public Response proceed(Request request) throws IOException {37 return proceed(request, streamAllocation, httpCodec, connection);38 }39 40 public Response proceed(Request request, StreamAllocation streamAllocation, HttpCodec httpCodec,41 RealConnection connection) throws IOException {42 43 ......44 // Call the next interceptor in the chain.45 RealInterceptorChain next = new RealInterceptorChain(46 interceptors, streamAllocation, httpCodec, connection, index + 1, request);47 Interceptor interceptor = interceptors.get(index);48 Response response = interceptor.intercept(next);49 50 ...... 51 52 return response;53 }54 }
在proceed
方法中的核心代码可以看到,proceed实际上也做了两件事:
- 创建下一个拦截链。传入
index + 1
使得下一个拦截器链只能从下一个拦截器开始访问 - 执行索引为
index
的intercept方法,并将下一个拦截器链传入该方法