分析之前可以参考一下我的前面的博客Retrofit 2 使用指南 ,熟悉一下它的基本使用。
本文用到的一些类图
初始化请求流程
先来看一下如何创建一个请求。
1 | public interface RequestService { |
异步请求
1 | public void getData(CallBack callBack){ |
同步请求
1 | public TestBean getDataSync(){ |
首先这里是创建一个 Retrofit
对象,这里用到了建造者模式。
那么就先来看一下 Builder().build()
的源码。
先来看一下 platform
这个变量,因为后面会用到它。通过 Builder
的构造函数,可以看到它是通过 Platform.get()
来实例化的,在 Android 平台上是一个 Platform.Android
对象。
1 | public Retrofit build() { |
再来看一下 Retrofit.create
。
这部分是重点,因为请求方法的执行其实就是执行到了这里动态代理对象的 invoke()
方法。后面会分开来介绍。
1 | public <T> T create(final Class<T> service) { |
执行请求流程
比如我们Demo中的一个请求方法的执行 mRequestService.getData()
,其实执行的方法体就是前面的动态代理对象的 invoke()
方法,返回一个 RequestService
接口中此方法定义的一个范型对象。
先来看一下如何生成 ServiceMethod
:ServiceMethod
和我们前面定义的请求方法是一一对应关系的,每个 Method 对应一个 ServiceMethod
。比如就像例子中我们调用 RequestService.getData()
方法就会生成一个对应的 ServiceMethod
对象,保存了 baseUrl、请求参数、请求类型等信息。
如果缓存里没有,则新建一个并放入到缓存中。至于这个 ServiceMethod
是我们后面再详细分析。
1 | ServiceMethod<?, ?> loadServiceMethod(Method method) { |
接着会根据 ServiceMethod
对象和参数生成一个 OkHttpCall
对象,然后再根据适配器的 adapter 方法把 OkHttpCall
转化为 ExecutorCallbackCall
(使用内置适配器时)。
这部分接下来也会详细介绍。
ServiceMethod
ServiceMethod
方法也比较简单,一些属性包含了一个Http请求的基本信息。
1 | final class ServiceMethod<R, T> { |
我们重点来看一下 ServiceMethod.Builder()
类。
1 | Builder(Retrofit retrofit, Method method) { |
它的构造函数会传入 Retrofit
和 Method
对象作为参数。
1 | public ServiceMethod build() { |
先来看一下 build
方法的调用流程(使用内置适配器时):
1 | ├── ServiceMethod.Builder().build() |
获取适配器
1 | public CallAdapter<?, ?> nextCallAdapter(@Nullable CallAdapter.Factory skipPast, Type returnType, |
这里会遍历我们添加的所有适配器,并调用适配器的 get()
方法,这个方法会根据当前请求方法的返回值类型来决定是否处理。
这里以内置的适配器来介绍一下:
ExecutorCallAdapterFactory.get():
1 | @Override |
获取转换器
1 | ├── ServiceMethod.createResponseConverter() |
1 | public <T> Converter<ResponseBody, T> nextResponseBodyConverter( |
处理方法注解
这一部分主要是根据方法注解的类型解析生成 ServiceMethod
的一些属性,比如:httpMethod
、hasBody
和 relativeUrl
等。ServiceMethod.Builder.parseMethodAnnotation()
:
1 | private void parseMethodAnnotation(Annotation annotation) { |
1 | private void parseHttpMethodAndPath(String httpMethod, String value, boolean hasBody) { |
OkHttpCall
这部分主要针对动态代理类中 OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args)
这段方法的执行。
前面我们说过,适配器处理对网络请求(内置适配器是生成的 Call 对象)都是委托给 OkHttpCall 来处理的。
先来看一下这个类:
1 | final class OkHttpCall<T> implements Call<T> { |
execute()
对应的就是同步请求方法。
主要来分析一下 enqueue()
方法,这个方法对应的就是异步请求方法。请求加入队列的方法最终也是由 okhttp3.Call
来执行的。那么就要来看一下 okhttp3.Call
是如何生成的。
1 | private okhttp3.Call createRawCall() throws IOException { |
serviceMethod.callFactory.newCall(request)
会调用 Retrofit.callFactory
来生成请求,Retrofit.callFactory
是通过 Retrofit.client(OkHttpClient client)
方法来设置的。
因此, okhttp3.Call
是最终由 OkHttpClient
来创建的,那么请求的执行也是由 OkHttpClient
来执行的。
CallAdapter 和 CallAdapter.Factory
CallAdapter
是一个接口,前文所说的适配器都是实现了这个接口。ExecutorCallAdapterFactory
的匿名内部类和 RxJava2CallAdapter
。
这里再来介绍一下 CallAdapter.Factory
类。它是 CallAdapter
的工厂类,是一个抽象类,ExecutorCallAdapterFactory
和 RxJava2CallAdapterFactory
都是继承这个类。
1 | public interface CallAdapter<R, T> { |
适配器处理请求流程
适配器处理请求是在动态代理类的 serviceMethod.callAdapter.adapt(okHttpCall)
方法处理。我们前面已经介绍过,使用使用内置适配器时,会由 ExecutorCallAdapterFactory.get()
方法生成的 CallAdapter
对象的 adapt()
方法执行。
1 | @Override public Call<Object> adapt(Call<Object> call) { |
这个方法返回了 ExecutorCallAdapterFactor.ExecutorCallbackCall
对象,以 Android.MainThreadExecutor
和 OkHttpCall
来作为参数。
1 | ExecutorCallbackCall(Executor callbackExecutor, Call<T> delegate) { |
在创建请求流程一节中我们展示的Demo中:
1 | Call<TestBean> call = mRequestService.getData(); |
mRequestService.getData()
返回的其实就是 ExecutorCallAdapterFactor.ExecutorCallbackCall
对象,后面的 call.enqueue
方式其实就是调用的 ExecutorCallAdapterFactor.ExecutorCallbackCall.enqueue()
方法。
返回相应结果时,需要调用客户端设置的回调方法,这个回调方法是在客户端设置的回调执行器中调用的,如果没有设置,那么默认就是 Android.MainThreadExecutor
。
1 | @Override public void enqueue(final Callback<T> callback) { |
这里我们可以看到,ExecutorCallbackCall
(使用内置适配器时)中相关的请求操作其实都是委托给 OkHttpCall
来执行的。执行的结果通过 Android.MainThreadExecutor
在主线程中执行回调函数。
具体的执行流程请看上面一节。
处理响应结果
这部分比较简单,主要是调用转换器的 convert()
方法把消息体转换成我们想要的数据类。Response<T>
这里用到了范型,是在定义请求方法时我们指定的类,比如 RequestManager.TestBean
。
这里以我们前面Demo中定义的 GsonConverterFactory
转换器来看一下执行流程:
1 | ├── OkHttpCall.parseResponse() |
OkHttpCall.parseResponse()
:
1 | Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException { |
至此,Retrofit 数据请求流程部分源码解析已经完成。