面试很容易被别人问到为什么你要用retrofit,为什么要用okhttp,为什么不只用其中一个等等的问题。是啊,为什么我要用呢?平常跟着网络的推荐,就去使用,没有去好好思考为什么大家都这么使用呢?带着这些问题,在网络上整理了一些资料,做些记录,后面找机会再对Retrofit和okhttp的源码做分析,好好再聊聊?
Retrofit和Okhttp是怎样的一个存在
- OKHTTP是一个相对成熟的HTTP网络请求方案。 HTTP网络请求这一项工作的代码开发,本身属于一个庞大工作量的事情,对于我们业务型的开发或者说公司业务并不在这块的开发,去动手做这一块就是舍本逐末的事情。不重复造轮子,所以我们日常开发一般都直接使用相对成熟的方案。例如早期安卓底层用的HttpURLConnection,OKHTTP和Volley,retrofit,android-async-http等都可供选择。
- 从本质上来说呢,HttpURLConnection和OkHttp与其他几个如Retrofit框架是有所区别的,这两个框架是根据HTTP协议封装的一套请求的客户端,而Retrofit框架等其他的几个框架则是在这两个框架的基础上做的封装,简化或优化代码调用的流程,以便于开发。从本质上讲,这几个框架无法脱离类似于OKHTTP的请求客户端。
- 那么市面上为什么选择OKHTTP的较多,原因就在于OKHTTP更加的成熟,事实上,OKHTTP也对HTTPURLConnection做了一层封装,他对于HTTP经常遇见的问题,如连接问题的自动恢复,可配置多个IP地址,在单一IP地址连接失败能换另一个地址连接访问,SSL的验证问题都提供了解决方案。可以让我们并不需要费这一部分精力和时间去做处理。
- 我们在2中已经说了,我们之所以使用Retrofit等框架的目的是为了简化和优化代码的调用,优化开发效率,当然你不去使用这些框架,直接使用OKHTTP也是可以,取决于实际应用。同时不同封装框架还有一些不同的优点,这些也是我们对比也是我们如何选择出适合自己的框架的理由。像是Volley框架在框架底层的网络访问做了一层封装,可以实现不同HTTP框架如OKHTTP或HTTPUrlConnnection的替换,如果考虑到中间需要替换底层网络请求框架,可以考虑使用Volley。Rtrofit相对比较晚出现的,他是基于OKHTTP做的封装,所以离不开OKHTTP,它相对于Volley解耦更加彻底,通过注解配置请求参数,通过工厂生成适配工具,完美适配了Rxjava等框架,也能在使用不同的反序列化工具,简化了我们的需要拿到数据之后再做解析的重复操作。
- 总来的说,如果我选择OKHTTP的原因是其在网络请求上相对做了更多更成熟的处理,那么选择Retrofit则是在我们怎么调用网络请求接口,以及从接口拿到数据后的这一方面做了比较成熟的处理。当然稳定性也是需要考虑的点,从市场上普遍的反馈以及开发团队是否对框架的持续支持,都是需要考虑的点。
- 至于我们经常说的okhttp与Retrofit的一起使用,更多的是指使用Retrofit请求,而使用okhttp进行底层配置,例如加入拦截器,加入SSO验证或其他身份认证,加入SSL拦截器等等,这些通过Retrofit中转配置给OKHTTP底层就行了。
- 另外,增加一层框架的封装势必性能也会带来一些影响。不过我个人觉得影响并不大,也没做过什么分析,以后有机会再谈吧。
Retrofit源码解析
先记录一些点
- 创建Retrofit对象并设置OKHTTP的配置的方式,使用了建造者模式
- 创建时相对应的主要的类有callFactory(HTTP请求客户端,,默认OkhttpClient,OKHTTP的东西先不谈),callbackExecutor(用户线程切换,在安卓平台使用了Handler的方式),adapterFactories(存放用于对Call进行处理的工厂类列表),converterFactories(存放用于序列化的工厂类列表)
- 通过注解,动态创建服务类和方法,使用了动态代理模式
- 创建过程中,首先根据每一个method类,生成ServiceMethod类,该类携带了方法的注解信息等其他信息,
- 根据method的信息创建一个对call处理的工厂类对象;
- 根据要解析成的类的类型,利用序列化的工厂类持有一个能对数据进行序列化的工具类;序列化的类是由我们自己设置的,默认也存在着一个;
- 根据注解获取相关对注解处理的对象;
- 这些处理注解对象会在后面与输入的参数合作,生成okhttp请求所需要的Request对象,而其他类则针对回调对象进行处理。
- 将ServiceMethod和输入参数赋值给OkhttpCall这个类,这个类在之后将配合callbackExecutor这个线程控制的类,以及ServiceMethod生成的Request对象,内部调用Okhttp进行请求和回调。
- 将OKhttpCall注入method持有的对于call处理的工厂类,这个类将返回一个用于回调的类给最外层,这个类就是我们利用Retrofit直接接触的类。而4中对于OKHTTP的请求过程就是在该类中进行。