您现在的位置是:首页 > 文章详情

OkHttp3源码详解(三) 拦截器

日期:2019-11-17点击:408

首先构造一个简单的异步网络访问Demo:

1. OkHttpClient client = new OkHttpClient(); 2. Request request = new Request.Builder() 3. .url("http://publicobject.com/helloworld.txt") 4. .build(); 6. client.newCall(request).enqueue(new Callback() { 7. @Override 8. public void onFailure(Call call, IOException e) { 9. Log.d("OkHttp", "Call Failed:" + e.getMessage()); 10. } 12. @Override 13. public void onResponse(Call call, Response response) throws IOException { 14. Log.d("OkHttp", "Call succeeded:" + response.message()); 15. } 16. }); 

2. 发起请求

OkHttpClient.newCall实际是创建一个RealCall实例:

1. @Override 2. public Call newCall(Request request) { 3. return new RealCall(this, request, false /* for web socket */); 4. } 

RealCall.enqueue实际就是讲一个RealCall放入到任务队列中,等待合适的机会执行:

1. @Override 2. public void enqueue(Callback responseCallback) { 3. synchronized (this) { 4. if (executed) throw new IllegalStateException("Already Executed"); 5. executed = true; 6. } 7. captureCallStackTrace(); 8. client.dispatcher().enqueue(new AsyncCall(responseCallback)); 9. } 

从代码中可以看到最终RealCall被转化成一个AsyncCall并被放入到任务队列中,任务队列中的分发逻辑这里先不说,相关实现会放在OkHttp源码分析——任务队列疑问进行介绍。这里只需要知道AsyncCall的excute方法最终将会被执行:

1. [RealCall.java] 2. @Override protected void execute() { 3. boolean signalledCallback = false; 4. try { 5. Response response = getResponseWithInterceptorChain(); 6. if (retryAndFollowUpInterceptor.isCanceled()) { 7. signalledCallback = true; 8. responseCallback.onFailure(RealCall.this, new IOException("Canceled")); 9. } else { 10. signalledCallback = true; 11. responseCallback.onResponse(RealCall.this, response); 12. } 13. } catch (IOException e) { 14. if (signalledCallback) { 15. // Do not signal the callback twice! 16. Platform.get().log(INFO, "Callback failure for " + toLoggableString(), e); 17. } else { 18. responseCallback.onFailure(RealCall.this, e); 19. } 20. } finally { 21. client.dispatcher().finished(this); 22. } 23. } 24. } 

execute方法的逻辑并不复杂,简单的说就是:

调用getResponseWithInterceptorChain获取服务器返回
通知任务分发器(client.dispatcher)该任务已结束
getResponseWithInterceptorChain构建了一个拦截器链,通过依次执行该拦截器链中的每一个拦截器最终得到服务器返回。

3. 构建拦截器链
首先来看下getResponseWithInterceptorChain的实现:

源码路径:okhttp3/RealCall.java

 // 开始执行整个请求 Response getResponseWithInterceptorChain() throws IOException { // Build a full stack of interceptors. // 拦截器栈 List<Interceptor> interceptors = new ArrayList<>(); // 前文说过的 普通拦截器 interceptors.addAll(client.interceptors()); // 重试拦截器,网络错误、请求失败等 interceptors.add(retryAndFollowUpInterceptor); // 桥接拦截器,主要是重构请求头即header interceptors.add(new BridgeInterceptor(client.cookieJar())); // 缓存拦截器 interceptors.add(newCacheInterceptor(client.internalCache())); // 连接拦截器,连接服务器,https包装 interceptors.add(new ConnectInterceptor(client)); // 网络拦截器,websockt不支持,同样是自定义 if (!forWebSocket) { interceptors.addAll(client.networkInterceptors()); } // 服务拦截器,主要是发送(write、input)、读取(read、output)数据 interceptors.add(new CallServerInterceptor(forWebSocket)); // 开启调用链 Interceptor.Chain chain = new RealInterceptorChain( interceptors, , originalRequest); return chain.proceed(originalRequest); } 

其逻辑大致分为两部分:

创建一系列拦截器,并将其放入一个拦截器数组中。这部分拦截器即包括用户自定义的拦截器也包括框架内部拦截器
创建一个拦截器链RealInterceptorChain,并执行拦截器链的proceed方法
接下来看下RealInterceptorChain的实现逻辑:

 public final class RealInterceptorChain implements Interceptor.Chain { private final List<Interceptor> interceptors; private final StreamAllocation streamAllocation; private final HttpCodec httpCodec; private final RealConnection connection; private final int index; private final Request request; private int calls; public RealInterceptorChain(List<Interceptor> interceptors, StreamAllocation streamAllocation, HttpCodec httpCodec, RealConnection connection, int index, Request request) { this.interceptors = interceptors; this.connection = connection; this.streamAllocation = streamAllocation; this.httpCodec = httpCodec; this.index = index; this.request = request; } @Override public Connection connection() { return connection; } public StreamAllocation streamAllocation() { return streamAllocation; } public HttpCodec httpStream() { return httpCodec; } @Override public Request request() { return request; } @Override public Response proceed(Request request) throws IOException { return proceed(request, streamAllocation, httpCodec, connection); } public Response proceed(Request request, StreamAllocation streamAllocation, HttpCodec httpCodec, RealConnection connection) throws IOException { ...... // Call the next interceptor in the chain. RealInterceptorChain next = new RealInterceptorChain( interceptors, streamAllocation, httpCodec, connection, index + , request); Interceptor interceptor = interceptors.get(index); Response response = interceptor.intercept(next); ...... return response; } } 

在proceed方法中的核心代码可以看到,proceed实际上也做了两件事:

创建下一个拦截链。传入index + 1使得下一个拦截器链只能从下一个拦截器开始访问
执行索引为index的intercept方法,并将下一个拦截器链传入该方法。
原文链接:https://www.bbsmax.com/A/MAzAEmQMz9/

原文链接:https://yq.aliyun.com/articles/727360
关注公众号

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。

持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。

转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。

文章评论

共有0条评论来说两句吧...

文章二维码

扫描即可查看该文章

点击排行

推荐阅读

最新文章