简介:大三学生党一枚!主攻Android开发,对于Web和后端均有了解。
个人语录:取乎其上,得乎其中,取乎其中,得乎其下,以顶级态度写好一篇的博客。
上一篇给男朋友介绍了Okhttp
的基础知识,OkHttpClient
,Request
,Call
,RealCall
以及同步执行和异步执行的源码解释。从这篇博客开始,会给男朋友深入分析拦截器链!拦截器链是OkHttp
的一个核心内容,非常非常重要,问到OkHttp
不可能不问拦截器链!我们先简介一下拦截器的思想,然后再对每一个拦截器做详细的介绍!
拦截器
一.拦截器的分类
这里仅介绍系统提供的几种拦截器,其实在官方的介绍中,拦截器的流程如图:
拦截器的流程:当一个请求被执行时,系统会执行 Application Intercepter
,可以理解为用户自定义的拦截器,然后执行Okhttp的核心拦截器链,经过一系列拦截器的加工和判断最终才会进行网络请求!
下面先简单介绍每一种拦截器的功能,后面会开辟专门的章节讲解每一个拦截器的源码!
1.1 retryAndFollowUpInterceptor
重试和重定向拦截器:该拦截器是拦截器链的第一个,它的作用就和它的名称一样,当我们访问某个服务出现某种异常时,比如该网站需要身份验证,又或者需要进行重定向,这些异常最后会返回到重定向拦截器这里被拦截,他可以对原始请求进行一些操作后自动进行重连尝试。列举几种情况:
- 需要验证:为原始的
Request
添加身份验证信息后,自动重新连接 - 重定向:原有网站不能提供服务,需要跳转到新的一个端口或者服务,那么将原始请求的
URL
更改为重定向指向的URL
,自动重新连接。
Question:是不是所有失败的情况都会重新连接?
并不是,只对某些异常做重新连接的尝试!它的优点在于,对于某些不严重的异常或者并不是错误引起的请求错误自动进行重试!!!
1.2 BridgeInterceptor
关于BridgeInterceptor的作用,官方的描述是这样的
Bridges from application code to network code.
First it builds a network request from a user
request. Then it proceeds to call the network.
Finally it builds a user response from the network response.
英文好的盆友肯定理解了,BridgeInterceptor
拦截器的作用就是把用户的Resquest
转换成符合网络规范的Request
,当服务器返回Response
时,又将复合网络规范的Response
转换成用户的Response
,这样的好处是什么?我们使用起来更方便了,不需要自己去定义请求头的一些格式,也无需要关心返回Response
的解压,把精力投放在业务需要上即可!
1.3 CacheInterceptor
缓存拦截器的作用,官方解释
Serves requests from the cacheand writes responses to the cache
简而言之,如果该请求之前已经执行过,并且Response被缓存了,如果经过判断,该缓存可用,就不需要再继续下面的拦截器请求了,直接返回该Response,节省了网络请求的时间,加快速度。能够被缓存的请求的请求方法一定是GET
,其他的请求方法都不会被缓存。CacheInterceptor的作用其很简单,但是内部的源码比较复杂,都会开辟专门章节进行讲解!
1.4 ConnectInterceptor
官方描述的作用
Opens a connection to the target serverand proceeds to the next interceptor.
就是开启一个和目标服务器的连接,然后就执行后面的CallServerInterceptor
拦截器了,其实更像是为后面的拦截器做铺垫,创建好一条Connection
!当然它的连接是如何创建的呢?后面会有介绍。
1.5 CallServerInterceptor
This is the last interceptor in the chain. It makes a network call to the server.
他是最后一个拦截器,它的作用就是通过创建好的链接,将Request
写入网络的IO流中,并从IO流中读取返回的Response
。
二.拦截器的原理
上面简单的介绍了几种拦截器的作用,但是Okhttp
是怎么实现拦截器链的呢?链是怎么形成的呢?还是得回到源代码中寻找答案!
首先看看RealCall
中的getResponseWithInterceptorChain()
方法
ResponsegetResponseWithInterceptorChain() 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));
//通过链表构建拦截器链Interceptro.Chain
Interceptor.Chain chain = new RealInterceptorChain(interceptors, null, null, null, 0,
originalRequest, this, eventListener, client.connectTimeoutMillis(),
client.readTimeoutMillis(), client.writeTimeoutMillis());
//最后调用了拦截器链的proceed()方法
return chain.proceed(originalRequest);
}
再来看看preceed()方法做了什么吧!
// Call the next interceptor in the chain.这里重新构建了一个拦截器链,但是index+1。
RealInterceptorChain next = new RealInterceptorChain(interceptors, streamAllocation, httpCodec,
connection, index + 1, request, call, eventListener, connectTimeout, readTimeout,
writeTimeout);
Interceptor interceptor = interceptors.get(index);//index==0,所以取出第一个
Response response = interceptor.intercept(next);//执行第一个拦截器。然后以后继续执行下一个拦截器得到Response,只有执行到最后一个拦截器才会得到Response,返回给最初的调用者。这也就是拦截器链的实现原理
三.总结
本篇简单的介绍了几种拦截器的作用,并介绍了拦截器的原理。后面我们会详细介绍每一种拦截器的源代码!!!男朋友听完都说好!!!
先别走,我有一个资源学习群要推荐给你,它是白嫖党的乐园,小白的天堂!
相关阅读: