OkHttp拦截器的实现原理

Posted 寸草之心

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OkHttp拦截器的实现原理相关的知识,希望对你有一定的参考价值。

今天项目中遇到需要将从push接收到的数据按照协议parse成应用层需要的结构化数据类型问题;因为push消息类型繁多,等待解析出的结构化数据类型也多样,有的还需要经过几步的parse过程;而且因为项目历史原因,使用Protocal Buffer(push的数据是字节形式的传递)。中间尝试了代理、装饰等模式,都失败了,最终还是使用了原始的继承解决问题;在解决问题个过程中也学习了下OkHttp中的拦截器实现,这里做简单记录:

  • ?拦截器的接口定义如下:

  技术分享

可以看到,在拦截器的回调中,我们可以拿到两个重要的参数Request和Response,而接口在回调时,会接收一个Chain类型的参数,这个参数保存了Request和Response的相关数据。

  • 看一个简单的Interceptor接口实现例子:

    技术分享

该拦截器实例的功能只是在请求发出前和接收到响应后,分别打印log。Response response=chain.proceed(request); 很重要,它是将拦截连串起来的关键。

  • 再看下,一个网络请求的应用吧:

    技术分享

跟进,OkHttpClient.Builder的addInterceptor()方法,可以看到,在OkHttp内部是使用了List保存了添加的所有拦截器。

   技术分享

  • 跟进client.newCall(request).execute();的执行过程,查看拦截器的串联过程:

    技术分享

从上面的方法中可以看到,请求默认会被构造成RealCall类型,再进一步查看RealCall的execute()方法:

   技术分享

上面的红色方框中这行代码,它并没有真正的执行网络请求,而只是简单地将请求放入请求池中,让它等待分派器的后续执行。而真正的执行体在上面的蓝色方框中,它封装了一个拦截器链(Chain),并调用了Chain的proced方法,传入原始的request对象,这里开始拦截器链的调用过程:

   技术分享

  • 查看proceed方法,可以看到,它使用循环+递归的方式,借助函数调用栈,将拦截器串联起来:

   技术分享

上面的代码中,真正执行网络请求的是最后一行绿色方框中的代码,而当存在多个拦截器时,每个拦截器在执行时都会在上图的蓝色方框中的代码地方阻塞,等待下一个拦截器的调用返回。

  •  为了说明清楚,下面分别以 拦截器链中有1个、2个拦截器的场景加以模拟:

技术分享

 

以上是关于OkHttp拦截器的实现原理的主要内容,如果未能解决你的问题,请参考以下文章

Android OkHttp3 :最简单&粗暴(使用与原理)讲解

面试官:简单说下 okHttp原理分析~

Android开发老生新谈:从OkHttp原理看网络请求

OkHttp面试之--OkHttp的整个异步请求流程

OKHTTP拦截器CallServerInterceptor的简单分析

Android网络请求库【OkHttp4.9.3】基本用法与原理分析