Okhttp之五种拦截器

原理:主要是通过 5 个拦截器和 3 个队列(同步队列,异步队列,等待队列)工作,内部实现通过一个责任链模式完成,将网络请求的各个阶段封装到各个链条中,实现了各层的解耦

5个拦截器都是哪些?有什么作用

  • RetryAndFollowUpInterceptor(重试和重定向拦截器)
    第一个接触到请求,最后接触到响应;负责判断是否需要重新发起整个请求 。重试与重定向拦截器主要处理Response
  • BridgeInterceptor(桥接拦截器)
    补全请求,并对响应进行额外处理,完成应用层和网络层的桥接
  • CacheInterceptor(缓存拦截器)
    请求前查询缓存,获得响应并判断是否需要缓存
  • ConnectInterceptor(链接拦截器)
    与服务器完成TCP连接 (Socket),内部维护一个连接池,负责连接复用、创建连接、释放连接
  • CallServerInterceptor(请求服务拦截器)
    与服务器通信;封装请求数据与解析响应数据(如:HTTP报文)。里面用的okio库,主要是segment的机制运用内存共享和复用,数据不需要进行二次copy,尽可能少的去申请内存,同时也就降低了GC的频率。强了流与流交互,优化缓存策略减小内存压力和性能消耗

RetryAndFollowUpInterceptor (重试和重定向拦截器)

状态码描述
1xx信息,服务器收到请求,需要请求者继续执行操作
2xx成功,操作被成功接收并处理
3xx重定向,需要进一步的操作以完成请求
4xx客户端错误,请求包含语法错误或无法完成请求
5xx服务器错误,服务器在处理请求的过程中发生了错误

HTTP Code 常用状态码

RetryAndFollowUpInterceptor 总结

  • 是整个责任链中的第一个,是首次接触到Request与最后接收到 Response的,主要功能就是判断是否需要重试与重定向。
  • 重试的前提是出现了 RouteException 或IOException 。一旦在后续的拦截器执行过程中出现这两个异常,就会通过 recover 方法进行判断是否进行连接重试。
  • 重定向发生在重试的判定之后,如不满足重试的条件,还需要进一步调用 followUpRequest 根据Response 的响应码(如果直接请求失败, Response都不存在就会抛出异常)。 followup 最大发生20次。

BridgeInterceptor(桥接拦截器)

请求头说明
Content-Type请求体类型(如 application/x-www-form-urlencoded)
Content-Length/Transfer-Encoding请求体解析方式
Host请求的主机站点
Connection:Keep-Alive默认保持长连接
Accept-Encoding:gzip接受响应体使用gzip压缩
Cookie Cookie身份识别
User-Agent用户信息,如操作系统、浏览器等

在补全了请求头后交给下一个拦截器处理,得到响应后,主要干两件事情:

  • 如果使用gzip返回的数据,则使用GzipSource包装便于解析。
  • 保存cookie,在下次请求则会读取对应的数据设置进入请求头,默认的 CookieJar 不提供实现

BridgeInterceptor总结:

对用户构建的 Request 进行添加或者删除相关头部信息,以转化成能够真正进行网络请求的 Request 将符合网络 请求规范的Request交给下一个拦截器处理,并获取 Response 如果响应体经过了GZIP压缩,那就需要解压,再构 建成用户可用的 Response 并返回

CacheInterceptor (缓存拦截器)

只有当互联网可用时才会返回缓存的响应,因为 OkHttp 就是这样设计的。

在进入 OkHttp Core 之前,我们必须拦截 Response 并添加 header(Cache-Control),所以它会被视为响应(带有 Cache-Control header)已经到来来自服务器,OkHttp Core 会尊重并缓存响应。
创建缓存拦截器

public class CacheInterceptor implements Interceptor {
  @Override
  public Response intercept(Chain chain) throws IOException {
    Request request = chain.request();
    Response respOnse= chain.proceed(request);
    String cache = request.header("Cache-Time");
    if (!Util.checkNULL(cache)) {//缓存时间非空
      Response response1 = response.newBuilder()
          .removeHeader("Pragma")
          .removeHeader("Cache-Control")
          //cache for cache seconds
          .header("Cache-Control", "max-age="+cache)
          .build();
      return response1;
    } else {
      return response;
    }
  }
}

配置缓存路径

public class CacheFile {
  Context mContext;
 
  public CacheFile(Context context) {
    mCOntext= context;
  }
 
  public Cache provideCache() {//使用应用缓存文件路径,缓存大小为10MB
    return new Cache(mContext.getCacheDir(), 10 * 1024 * 1024);
  }
}

指定了缓存的大小为10MB。这里如果缓存的数据量大于这个值,内部会使用lur规则进行删除。

使用

OkHttpClient client = new OkHttpClient.Builder()
         .addNetworkInterceptor(new CacheInterceptor())//缓存拦截器
         .cache(new CacheFile(mAppliactionContext).provideCache())//缓存空间提供器
         .connectTimeout(8, TimeUnit.SECONDS)
         .readTimeout(3, TimeUnit.SECONDS)
         .writeTimeout(3, TimeUnit.SECONDS)
         .build();

ConnectInterceptor(链接拦截器)

拦截器中的所有实现都是为了获得一份与目标服务器的连接,在这个连接上进行HTTP数据的收发。

CallServerInterceptor(请求服务拦截器)

CallServerInterceptor完成HTTP协议报文的封装和解析。

addInterceptor与addNetworkInterceptor的区别

二者通常的叫法为应用拦截器和网络拦截器,从整个责任链路来看,应用拦截器是最先执行的拦截器,也就是用户自己设置request属性后的原始请求,而网络拦截器位于ConnectInterceptor和CallServerInterceptor之间,此时网络链路已经准备好,只等待发送请求数据。

首先,应用拦截器在RetryAndFollowUpInterceptor和CacheInterceptor之前,所以一旦发生错误重试或者网络重定向,网络拦截器可能执行多次,因为相当于进行了二次请求,但是应用拦截器永远只会触发一次。另外如果在CacheInterceptor中命中了缓存就不需要走网络请求了,因此会存在短路网络拦截器的情况。
其次,如上文提到除了CallServerInterceptor,每个拦截器都应该至少调用一次realChain.proceed方法。实际上在应用拦截器这层可以多次调用proceed方法(本地异常重试)或者不调用proceed方法(中断),但是网络拦截器这层连接已经准备好,可且仅可调用一次proceed方法。
最后,从使用场景看,应用拦截器因为只会调用一次,通常用于统计客户端的网络请求发起情况;而网络拦截器一次调用代表了一定会发起一次网络通信,因此通常可用于统计网络链路上传输的数据。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
为了满足广大Android开发爱好者与从业者的学习需求,我们精心整理并上传了一份全面而实用的Android项目资源包。这份资源包内容丰富,涵盖了从基础知识到实战应用的全方位内容,旨在为开发者们提供一个便捷、高效的学习平台。 一、文件手册 资源包中的文件手册部分,详细记录了Android开发的核心知识点和常用技术。无论是初学者还是有一定经验的开发者,都能从中找到所需的学习资料。手册采用了简洁明了的排版方式,使得查阅更加方便快捷。同时,手册内容深入浅出,既适合新手入门,也能为老手提供有价值的参考。 二、项目实战与练习 为了让学习者能够将理论知识与实践相结合,我们特别准备了项目实战与练习部分。这部分内容包含了多个精心设计的Android项目案例,从需求分析、设计思路到实现过程,都有详细的讲解和代码示例。学习者可以通过实际操作,深入了解Android开发的整个流程,提升自己的实战能力。 此外,我们还提供了一系列练习题,旨在巩固所学知识,检验学习成果。这些练习题既有基础题,也有难度较高的挑战题,适合不同层次的学习者进行练习。 三、Android开发工具集 在Android开发过程中,选择合适的工具能够大大提高开发效率。因此,我们整理了常用的Android开发工具集,包括开发工具、测试工具、性能优化工具等。这些工具都是经过我们精心筛选和测试的,能够帮助开发者们更加高效地进行Android开发工作。 总的来说,这份Android项目资源包是一份不可多得的学习资料,无论你是初学者还是有一定经验的开发者,都能从中受益匪浅。我们希望通过这份资源包,为广大Android开发爱好者与从业者提供一个更加便捷、高效的学习平台,共同推动Android开发领域的发展。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值