DEVLOG 1.28 网络请求框架(下)-- OkHttp中的Interceptor和Retrofit源码分析
距离上一篇网络请求OkHttp的源码解析已经过去一个月了,我人傻了,时间过得好快,夜幕就要降临。这篇的内容主要是对于Retrofit的源码分析。虽然OkHttp中还剩下Interceptor,但是OkHttp中的Interceptor我看了一下感觉也没啥好说的,所以我想在这里简单说两句算了。
OkHttp中的Dispatcher将请求放入了线程池,然后由Interceptor进行一个责任链的处理,有重试重定向的逻辑的,有构建请求头,取出Cookie的逻辑的等等,主要的网络这块的使用的是Java的Socket api,所以我们在OkHttp这里也看不到特别底层的逻辑。
行,所以重点是放在Retrofit的源码解析。
本文行文的主要逻辑是顺着一个成功的网络请求从动态代理开始,一直到解析完成结束。
内容分成以下章节
Retrofit实例的构建过程
ServiceMethod以及ServiceMethod的生成
网络请求的开始
网络返回结果的解析
Ok,Start your engine!


Retrofit实例的构建过程
Retrofit的实例我们都是通过builder模式进行构建,举个例子:
我们需要配置CallAdapterFactory,这个是将我们的网络请求方法的返回值使用Retrofit提供的Call包装起来;配置ConverterFactory是转化我们的网络请求的返回值,比如从json类型变成具体的Java bean。
下面我们具体的看看build过程
Retrofit#build
通过观察Retrofit的build过程,我们可以看到Retrofit中被设置了这样几个关键的属性:

CallFactory:这个就是一个OkHttpClient,如果没有在构建时传入,会自行初始化。
CallBackExecutor:网络请求完成时回调线程池。在后面查看具体实现时,在Android中是基于Handler实现的,将Runnable回调发送到主线程
CallAdapterFactory:如果在build过程中添加了Factory,将会构建关于这些Factory的列表。然后将一个默认的Factory添加进列表的末尾(DefaultCallAdapterFactory)
ConverterFactory:和CallAdapterFactory类似,但是如果没有传入定义的Factory,默认的列表是空的。
ServiceMethod以及ServiceMethod的生成
下一步我们通常根据Retrofit的实例,调用create方法,通过传入一个包含了网络请求的方法、注解等的接口文件的Class对象。这个过程其实就是动态代理的过程。
关于动态代理,我们主要看一下Proxy.newProxyInstance中的实现。首先判断一下当前的方法是否是接口的默认方法,如果是,不需要代理;再判断有无继承自Object的方法,有的话也不用修改它的默认实现。
对于定义在Interface中的空请求方法,Retrofit调用了loadServiceMethod,首先构建ServiceMethod对象。
ServiceMethod就是使用了装饰模式对于Service类(网络请求接口文件)中的方法的包装。提供了解析注解,调用CallAdapter执行CallAdapt过程(姑且我这么说,其实就是将返回的数据类型使用Call包装),Converter进行解析过程。它在Retrofit中的具体实现类就是HttpServiceMethod。
Retrofit#loadServiceMethod
这里解析了定义在方法上的注解,将解析完成的请求方法缓存在map中。
综上所述,大体的框架已经搭建好,我们现在知道CallAdapt和Convert过程都在HttpServiceMethod中,我们进去看看。
CallAdapt过程的实现
上面的ServiceMethod.parseAnnotations方法会调用HttpServiceMethod中的同名方法:
在这个方法中,会使用createCallAdapter从CallAdapterFactory的列表中搜索可用的CallAdapterFactory:
同时也会从ConverterFactory中搜索可以用的Converter。这两个部分的逻辑比较相似,所以我们着重看CallAdapterFactory这块的处理。
上面的方法中,第一个get是从Factory列表中获取合适的工厂类,第二个get是具体的工厂方法的get:
这个方法的返回值是一个CallAdapter对象。可以看到在这个方法中创建的了一个CallAdapter的匿名内部类,并且重写了responseType和adapt方法。adapt方法主要做的就是adapt的过程。我们可以看到具体的Call对象的实现类是ExecutorCallbackCall这个类。
为了避免大家的逻辑混乱,我们首先看看几个Call之间的关系:

在Retrofit中也定义了Call。相对于OkHttp中处理请求的Call,retrofit中的Call是其装饰。
ExectuorCallbackCall也是一个Call,但是其针对请求的完成会通过executor回调到主线程:
delegate指的是OkHttpCall,OkHttpCall的enqueue方法也是基于OkHttp中的Call的对应方法,可以看到在回调onResponse时,交给了Executor处理。
这里的Executor是MainThreadExecutor,它将上面的onRepsonse回调发送到了主线程执行。
网络请求的开始和解析
OkHttpCall#enqueue
OkHttpCall这个定义在Retrofit中的类就是对于OkHttp.Call的包装,也基于了它的enqueue方法:
对于正确返回的数据会进行解析parseResponse,并且使用Converter转换成正确的Java bean:
到这里一个完整的分析过程就结束了,上面的流程总结就是如下的图:

Retrofit 真的不复杂~