注意:Retrofit 的源码是基于 2.0.1
一、切面编程
Okhttp 作为一个网络库是非常好的了,因为它采用了AOP切面思想(那些 Interceptors),也实现高内聚低耦合,但是在实际使用的时候有一些问题:
用户网络请求的接口配置繁琐,尤其需要配置复杂请求body 、请求头 的时候
数据解析过程中需要用户手动拿到 responseBody 进行解析,(请求参数)不能复用
无法适配自动进行线程切换
存在嵌套的网络请求(如:UserId 获取到之后再获取用户详细信息,详细信息获取后再下单),就会陷入“回调地狱”
基于此,Retrofit 就诞生了,它主要解决 2 个问题:
请求前:统一配置网络的请求头,一致适配请求 request
请求后:数据适配(解析json数据)、线程切换
Retrofit 总共 16个类,却采用了 8 种设计模式。
二、Retrofit 类的本身设计思想
2.1 Retrofit 的整体使用
总体分为4个步骤:
构建一个Retrofit
基于访问接口创建一个 接口类型的对象
基于接口类型的对象以及参数构建一个 Okhttp Call
将请求 Call 添加到 Okhttp 的请求队列
1 | //第一步 |
其中,接口 GitHubService.java 的代码可能是这样的 :
1 | public interface GitHubService { |
根据上面的代码,我们可以有几个疑问:
看第二步,貌似我们的接口被直接使用了?根据我们学习的 Java 知识,接口不能被直接使用啊,没有接口实例啊
第三步传入的 参数 “octocat” 到底去哪里了
url 到底怎么形成的?因为我们传入的只有一个主域名 “https://api.github.com/"
为什么所有的请求都是同样的方式
当你一行行看代码的时候就完蛋了,就会陷入细节,应该先看框架,看大体,思路流程好了之后再看细节。
参数大于 5 个 && 带有可选参数,我们就可以使用构建者模式,这是使用 Builder 的一个原则。
三、Retrofit 设计的 AOP 思想
从代码:
GitHubService service = retrofit.create(GitHubService.class);
可以看出,retrofit 肯定创建了接口子类对象了, 不然不可能给接口变量赋值。在 Retrofit 类中这个 create 方法的实现如下:
1 | public <T> T create(final Class<T> service) { |
从上面可以看出来,这是动态代理实现的。它会生成一个
四、是否可以作为单例
Retrofit 在使用的时候,能不能封装成单例呢?很多同学在 build 出来 Retrofit 对象后,将其作为单例保存,但其实不建议这么做。老师说的是可能带来内存泄漏,在 build 的时候,会有很多变量都会保存起来在 Retrofit 中,都会一直占内存。(对于这个论据不太认可,网络是会贯穿整个 App 使用周期的,所以网络的对象持续整个 App 生命周期感觉问题也不大)
如果网络请求非常非常频繁,比如股票,那我们就可以考虑 netty 。普通 App 的请求使用完就可以销毁。
五、ServiceMethod 的存在价值
注解的使用:
apt 技术:生成代码
注解 + 反射 运用
ServiceMethod 主要作用就是解析注解,解析请求返回值
将接口转变为 Okhttp 的 Call ,把注解和传入的参数一起封装在里面。所以,一个请求接口对应一个 ServiceMethod ,当一个 interface 中有多个 方法时,就会对应多个 ServiceMethod 。
默认的话,获取到的 Call 是 ExecutorCallbackCall
ServiceMethod 中封装了所有的变量,所以 toRequest 方法可以利用这些变量(包括 post/get 等)封装出一个 OKhttp 的 Request 对象。