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
并被放入到任务队列中,任务队列中的分发逻辑这里先不说,相关实现会放在OkHttp源码分析——任务队列疑问进行介绍。这里只需要知道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 List<Interceptor> interceptors = new ArrayList<>(); 6 // 前文说过的 普通拦截器 7 interceptors.addAll(client.interceptors()); 8 // 重试拦截器,网络错误、请求失败等 9 interceptors.add(retryAndFollowUpInterceptor); 10 // 桥接拦截器,主要是重构请求头即header 11 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 List<Interceptor> interceptors; 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<Interceptor> 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方法,并将下一个拦截器链传入该方法