Header
之前对 OkHttp 进行过源码分析了,那么今天就来讲讲 Retrofit 。
Retrofit 其实是对 OkHttp 进行了一层封装,让开发者对网络操作更加方便快捷。
相信绝大多数的 Android 开发者都有使用过的经历。其 restful 风格的编程俘获了众多人的心。
废话就不多讲了,下面就要对 Retrofit 进行源码解析。
本文解析的 Retrofit 基于 v2.3.0 ,GitHub 地址:https://github.com/square/retrofit
Retrofit 使用方法
直接抄官网的:
第一步,声明 API 接口:
1 | public interface GitHubService { |
第二步,构造出 Retrofit
对象:
1 | Retrofit retrofit = new Retrofit.Builder() |
第三步,得到 API 接口,直接调用:
1 | GitHubService service = retrofit.create(GitHubService.class); |
最后,就是调用 repos
执行 Call :
1 | // sync |
请求源码解析
我们先来看看发出网络请求部分的源码。
Retrofit.Builder
首先切入点就是 Retrofit.Builder
。
在 Retrofit.Builder
中有以下的方法:
- client : 设置 http client,默认是 OkHttpClient,会调用
callFactory
方法 - callFactory : 设置网络请求 call 的工厂,默认就是上面的 OkHttpClient
- baseUrl : api 的 base url
- addConverterFactory : 添加数据转换器工厂
- addCallAdapterFactory : 添加网络请求适配器工厂
- callbackExecutor : 回调方法执行器
- validateEagerly : 是否提前解析接口方法
这些都是用来配置 Builder
的。
那么我们来看下 Builder
的构造方法:
1 | public Builder() { |
来个小插曲,我们来看下 Retrofit 是如何确定平台的:
Platform
1 | private static final Platform PLATFORM = findPlatform(); |
从上面的代码中可以看到,是通过反射判断有没有该类来实现的。若以后在开发的过程中有需要判断平台的需求,我们可以直接将该段代码 copy 过来。
接着,在创建 Builder
对象并进行自定义配置后,我们就要调用 build()
方法来构造出 Retrofit
对象了。那么,我们来看下 build()
方法里干了什么:
1 | public Retrofit build() { |
在 build()
中,做的事情有:检查配置、设置默认配置、创建 Retrofit
对象。
关于上面种种奇怪的类,我们先不关心,因为之后我们遇到了再分析。我们先把目光聚焦在 Retrofit
类上。
Retrofit
Retrofit
类的构造方法没什么好看的,在这就不讲了。
得到 Retrofit
对象后就是调用 create(final Class<T> service)
方法来创建我们 API 接口的实例。
所以我们需要跟进 create(final Class<T> service)
中来看下:
1 | public <T> T create(final Class<T> service) { |
在上面的代码中,最关键的就是动态代理。实际上,进行网络操作的都是通过代理类来完成的。如果对动态代理不太懂的同学请自行百度了,这里就不多讲了。
重点就是
1 | // 将接口中的方法构造为 ServiceMethod |
这三句代码,下面我们着重来看。
在代理中,会根据参数中传入的具体接口方法来构造出对应的 serviceMethod
。ServiceMethod
类的作用就是把接口的方法适配为对应的 HTTP call 。
1 | ServiceMethod loadServiceMethod(Method method) { |
可以看到在内部还维护了一个 serviceMethodCache
来缓存 ServiceMethod
,以便提高效率。我们就直接来看 ServiceMethod
是如何被创建的吧。
ServiceMethod.Builder
发现 ServiceMethod
也是通过建造者模式来创建对象的。那就进入对应构造方法:
1 | public Builder(Retrofit retrofit, Method method) { |
在构造方法中没有什么大的动作,那么就单刀直入 build()
方法:
1 | public ServiceMethod build() { |
在 build()
中代码挺长的,总结起来就一句话:就是将 API 接口中的方法进行解析,构造成 ServiceMethod
,交给下面的 OkHttpCall
使用。
基本上做的事情就是:
- 创建 CallAdapter ;
- 创建 ResponseConverter;
- 根据 API 接口方法的注解构造网络请求方法;
- 根据 API 接口方法参数中的注解构造网络请求的参数;
- 检查有无异常;
代码中都是注释,在这里就不详细多讲了。
ServiceMethod serviceMethod = loadServiceMethod(method);
这句代码我们看完了,那么看接下来的 OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
。
OkHttpCall
在 OkHttpCall
的构造器中没什么大动作,搞不了大事情的:
1 | OkHttpCall(ServiceMethod<T> serviceMethod, Object[] args) { |
而真正搞事情的是 serviceMethod.callAdapter.adapt(okHttpCall);
这句代码。
ExecutorCallAdapterFactory
在 Retrofit 中默认的 callAdapterFactory 是 ExecutorCallAdapterFactory
。我们就进入它的 get(Type returnType, Annotation[] annotations, Retrofit retrofit)
看看吧,返回了一个匿名类 CallAdapter<Object, Call<?>>
,在其中有 adapt(Call<Object> call)
方法:
1 | @Override |
可以看到它 return new ExecutorCallbackCall<>(callbackExecutor, call);
。ExecutorCallbackCall
是实现了 retrofit2.Call
,这里注意下,是 Retrofit 中的 Call 而不是 OkHttp 中的 Call 。使用了装饰者模式把 retrofit2.Call
又包装了一层。
在得到了 ExecutorCallbackCall
,我们可以调用同步方法 execute()
或异步方法 enqueue(Callback<T> callback)
来执行该 call 。
ExecutorCallAdapterFactory.ExecutorCallbackCall
那我们就跟进同步方法 execute()
吧,异步的 enqueue(Callback<T> callback)
就不看了。了解过 OkHttp 的同学应该都知道这两个方法的区别,就是多了异步执行和回调的步骤而已。
1 | @Override |
所以,其实就是调用了 OkHttpCall
的 execute()
方法。
所以我们又要回到 OkHttpCall
中了。
OkHttpCall
1 | @Override public Response<T> execute() throws IOException { |
在 execute()
做的就是将 Retrofit 中的 call 转化为 OkHttp 中的 call 。
最后让 OkHttp 的 call 去执行。
至此,Retrofit 的网络请求部分源码已经全部解析一遍了。
剩下的就是响应部分了,趁热打铁。
响应源码解析
我们可以看到 OkHttpCall.execute()
中的最后一句:parseResponse(call.execute())
。
所以对响应的处理就是 parseResponse(okhttp3.Response rawResponse)
这个方法了。
OkHttpCall
1 | Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException { |
在 parseResponse(okhttp3.Response rawResponse)
中主要是这句代码:
T body = serviceMethod.toResponse(catchingBody);
将 ResponseBody
直接转化为了泛型,可以猜到这也是 Converter 的功劳。
ServiceMethod
1 | T toResponse(ResponseBody body) throws IOException { |
果然没错,内部是调用了 responseConverter
的。
BuiltInConverters
BuiltInConverters
中有好几种内置的 Converter 。并且只支持返回 ResponseBody
。我们来看下它们的实现:
1 | static final class StreamingResponseBodyConverter |
其实说白了就是将 ResponseBody
转化为对应的数据类型了。比如在 GsonConverterFactory
中就是把 ResponseBody
用 gson 转化为对应的类型,有兴趣的同学可以自己看下。这里也没什么神秘的,相信大家都懂的。
到这里就把 Retrofit 响应部分的源码解析完毕了。
大家自行消化一下吧。
我自己也写得头晕了。。。笑 cry
Footer
最后,相信大家已经了解了 Retrofit 到底是怎么一回事了。
Retrofit 内部访问网络仍然是通过 OkHttp ,而只是把构造请求和响应封装了一下,更加简单易用了。
还有,看过框架源码的都知道在源码中有很多设计模式的体现,比如建造者模式、装饰者模式以及 OkHttp 中的责任链模式等。这些也正是值得我们学习的地方。
好啦,今天结束了。如果有问题的同学可以留言咯。
Goodbye