锦囊篇|一文摸懂 OkHttp
前言
在面试中,OkHttp作为我们基本属于必用的第三方库来说,也是一个非常重要的考点,所以对其原理的掌握也会让我们的能力得到一定的提升。
OkHttp官网地址:https://square.github.io/okhttp/
基本使用
先一段引入关于OkHttp的使用,这是直接拉取了官网挂着的使用方法。因为在一般的使用过程中,后台可能会通过比较带有的session
或者cookie
来判断当前用户是否和缓存的用户相同,所以一般一个项目整体使用单例模式来创建OkHttpClient
的对象。
源码解析
这是我们的在okhttp
中使用的方法,整个项目的解析将围绕下面5个类进行。
OkHttpClient: 全局管理者
Request: 请求体
Call: 请求发起者
Callback: 数据接收通道
Response: 响应数据体
OkHttpClient、Request
首先是OkHttpClient
和Request
。
为什么这两个一起讲解呢?因为两个构造方式相同OkHttpClient
是一个全局掌控者,Request
是一个请求体的封装。
能看到OkHttpClient
的内部元素很多,但是我们很多时间并不会进行直接的使用,是因为他自己已经做了很多层的封装,另外他们这种创建对象的模式又称为建造者设计模式。
对建造者设计模式做一个比较通俗的介绍,就是将我们草稿图上的数据应用到真实的场景中去。
但是说了这么久,还是有一个问题啊,我没看到他对数据进行了使用啊??别着急,现在我们进入我们的使用环节了。
Call:任务的执行者
接下来就是Call
这个类,根据模版写法,我们知道需要将封装好的Request
请求体数据塞入OkHttpClient
中返回的就是一个Call
。
通过进入newCall()
方法,我们知道返回的数据其实是实现Call
的接口一个具体类RealCall
,具体操作我们不用知道,我们只用知道返回的一个具体类是什么就可以了,因为往后的操作都是围绕一个具体的东西展开的。
在看模版的下一句话call.enqueue(...)
,进入函数,我们可以看到下述的函数。
其他都还好,直接看到上述最后一行代码,因为我们需要将任务发布出去,并且拿到数据,那么自然需要一个分发器了和一个接收回馈数据的通道了,这显然就是我们上文中OkHttpClient
中所看到的dispatcher
和我们在外部定义好的Callback
==> responseCallback
。
想来对整个的处理过程已经有一个比较详细的讲解了,但是我们还是没有看到数据的返回操作,甚至说具体的运行,不过我们能够注意到一个中途意外冒出的变量executorService
,这个变量是从哪里来的呢?
溯源我们能够发现,他在Dispatcher
中就已经有过了初始化操作。
一看到要说ThreadPoolExecutor
,哦哦哦哦!线程池,但是和什么线程池长得特别像呢?进入已经定义好的Executors
类中查找,能够查找到如下的代码段:
是不是有点像呢?那好,我们就认定了它是我们的CachedThreadPool
线程池。
ok!fine!用的线程池来进行异步操作,那肯定就是说明里面有一个线程了,那这个线程是啥,我们是否心里有点数呢?如果没有,也没啥关系,下面我们将继续引出。
那接下来就又不是什么大问题了,主要就看到我们的注释1、2、3。
executorService.execute(this)
:对于线程池而言运行的显然是线程,而this
几就是我们的AsyncCall
,通过对AsyncCall
的观察我们也是能够得知它是继承了Runnable
的,所以异步进行的操作来源我们也已经清楚了。responseCallback.onFailure()
,也就是通过我们传入的Callback
接收数据的错误反馈。client.dispatcher.finished(this)
:为什么需要这个呢?其实他原本有这样的一段英文注释,This call is no longer running!
,也就是说明这个函数是为了通知Dispatcher
我们的AsyncCall
已经完成了运行。
又开始有问题了吧,看着就着急。咋就没看到responseCallback()
的onResponse
方法的使用呢???
那我们做一个猜测吧,其实我看了一下基本也是正解了。我们的不是Runnable
嘛,而数据是放在线程池中run()
来运行的,那么onResponse()
方法的出现应该是在run()
的这个函数中了。接下来我们继续收看代码
在这里的注释(2)中,我们很幸运的看到了onResponse()
的方法调用了。好那接下来就是下一个问题了,Response
是从哪里来的????
Response的诞生
上面不是写着嘛??getResponseWithInterceptorChain()
这个函数里来的呗。哇哦!!没错了,那它是怎么来的? 🤔🤔🤔
又要看代码了,好烦好烦。。。
为了尽量让代码简洁明了,我截取了一些关键代码,以供参考。
其实他就是通过一堆的拦截器来获取数据的,但是显然这里不是终点站,因为我们看到的return
中就还是一个函数,说明答案还在这个函数中。通过观察我们很容易得知,这个的操作的具体类是一个叫做RealInterceptorChain
的类。
如图所示,哪个拦截器能拦截成功,就会返回我们需要的数据Response
,当然这个数据你需要注意,并不一定是成功的数据,一般来说数据成功的获取都需要走到我们的响应拦截器之后才能真正的成功。
CacheInterceptor缓存拦截器的源码解读
这里我们需要重点讲解一下CacheInterceptor
这个类,我们截取他的intercept()
方法,因为里面涉及了我们面试时可能会频繁使用的响应码
总结
最后我们通过一张图来完成对整个OkHttp
的工作流程梳理。
版权声明: 本文为 InfoQ 作者【ClericYi】的原创文章。
原文链接:【http://xie.infoq.cn/article/4a260947f3d13730047f17eaa】。文章转载请联系作者。
评论