OKHTTP源码分析(二)同步方法以及拦截器链
来源:互联网 发布:淘宝客推广专区在哪里 编辑:程序博客网 时间:2024/05/29 03:44
前一章我们分析了OKHTTP处理异步方法,这一章我们来分析一下OKHttp处理同步方法。
同步方法调用的是Realcall的execute方法
@Override public Response execute() throws IOException { synchronized (this) { if (executed) throw new IllegalStateException("Already Executed"); executed = true; } captureCallStackTrace(); try { client.dispatcher().executed(this); Response result = getResponseWithInterceptorChain(); if (result == null) throw new IOException("Canceled"); return result; } finally { client.dispatcher().finished(this); } }RealCall方法先调用Dispatcher的executed方法 ,Dispatcher执行的只是将call加入runningSyncCalls(运行中的同步队列)。之后会调用getResponseWithInterceptorChain()方法,我们先不看getResponseWithInterceptorChain()方法,我们先跳到异步任务执行中, 异步任务的执行是在AsycCall的execute中
@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); } }
可以看到不管是RealCall的execute方法还是AsycCall的execute方法,都执行了getResponseWithInterceptorCharin(),可见这个方法很重要哈!这个方法构建了okhttp的拦截器链,okhttp的重连,缓存等重要特性,都是通过一个个的拦截器来完成的,辣磨我们来看一看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 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, this, eventListener, client.readTimeoutMillis(), client.writeTimeoutMillis()); return chain.proceed(originalRequest); }}(interceptors, null, null, null, 0, originalRequest, this, eventListener, client.readTimeoutMillis(), client.writeTimeoutMillis()); return chain.proceed(originalRequest); }}
从上面的代码可以看出getResponseWithInterceptor先将拦截器加入拦截器数组,然后构建拦截器链 RealInterceptorChain ,并返回RealInterceptorChain.proceed()
public Response proceed(Request request, StreamAllocation streamAllocation, HttpCodec httpCodec, RealConnection connection) throws IOException { if (index >= interceptors.size()) throw new AssertionError(); calls++; // If we already have a stream, confirm that the incoming request will use it. if (this.httpCodec != null && !this.connection.supportsUrl(request.url())) { throw new IllegalStateException("network interceptor " + interceptors.get(index - 1) + " must retain the same host and port"); } // If we already have a stream, confirm that this is the only call to chain.proceed(). if (this.httpCodec != null && calls > 1) { throw new IllegalStateException("network interceptor " + interceptors.get(index - 1) + " must call proceed() exactly once"); } // Call the next interceptor in the chain. RealInterceptorChain next = new RealInterceptorChain(interceptors, streamAllocation, httpCodec, connection, index + 1, request, call, eventListener, readTimeout, writeTimeout); Interceptor interceptor = interceptors.get(index); Response response = interceptor.intercept(next); // Confirm that the next interceptor made its required call to chain.proceed(). if (httpCodec != null && index + 1 < interceptors.size() && next.calls != 1) { throw new IllegalStateException("network interceptor " + interceptor + " must call proceed() exactly once"); } // Confirm that the intercepted response isn't null. if (response == null) { throw new NullPointerException("interceptor " + interceptor + " returned null"); } if (response.body() == null) { throw new IllegalStateException( "interceptor " + interceptor + " returned a response with no body"); } return response; }}
上面的核心逻辑是构建next 拦截器链,然后执行拦截器的intercept方法,将next链传递给intercept方法,intercept方法会返回response。过程相当于执行拦截器链中每一个拦截器的intercept方法,然后每个拦截器返回response,最终构建成真正需要返回的Response.
最后 调用Dispatcher.finished方法,将执行结束的任务从任务队列中删除。
总结:不管是同步方法还是异步方法,最终都会构建拦截器链,拦截器链中构建拦截器数组,并且递归执行拦截器的拦截方法,并返回最终的Response.
阅读全文
0 0
- OKHTTP源码分析(二)同步方法以及拦截器链
- OkHttp 3.7源码分析(二)——拦截器&一个实际网络请求的实现
- OkHttp 3.7源码分析(二)——拦截器&一个实际网络请求的实现
- okhttp源码分析(二)-RetryAndFollowUpInterceptor过滤器
- OKHTTP源码分析(一)异步方法
- springMVC源码分析--HandlerInterceptor拦截器调用过程(二)
- springMVC源码分析--HandlerInterceptor拦截器调用过程(二)
- okHttp 二 拦截器解析及责任链模式
- OKHTTP的拦截器以及https访问
- OKhttp源码解析---拦截器之RetryAndFollowUpInterceptor
- OKhttp源码解析---拦截器之BridgeInterceptor
- OKhttp源码解析---拦截器之CacheInterceptor
- OKhttp源码解析---拦截器之ConnectInterceptor
- OKhttp源码解析---拦截器之CallServerInterceptor
- OkHttp 源码解析(3) Interceptor 拦截器
- Okhttp源码解析之Interceptor(拦截器)
- OKHttp源码分析(二)之RequestBody
- OkHttp的拦截器机制分析
- kafka配置参数
- linux下PPPoE Server测试环境搭建
- SpringMVC报404的一种可能
- maven新增tomcat插件
- JPA查询出现死循环
- OKHTTP源码分析(二)同步方法以及拦截器链
- pandas 读取csv Initializing from file failed
- javamail诡异的504异常
- centos7开通ssh服务
- bootstarp-table表格中嵌套多个BUTON按钮实现
- 关于如何将Eclipse中@author进行修改的解决方法
- 看完《第一行代码》再看什么书可以进一步提高?
- Caused by: java.lang.ClassNotFoundException: javassist.util.proxy.MethodFilter
- Java 内部类