行业动态

「Android技术汇」Retrofit2 源码解析和案例说明

作者:admin    发布时间:2019-12-08 20:36     浏览次数 :

[返回]

  唉~ 最近可谓是 Alexander(亚历山大)呀!因为转了几篇好友“龙大湿”写的 Pokemon Go 的文章,一直有人说我不务正业,特别是 Pokeman 4 的文章里图片有个小错误,哎哟,评论圈里可谓是炸开了锅。还有某位仁兄专门撰文反驳我朋友文章的错误,害“龙大湿”天天以泪洗面。

  今天为了补偿大家,就带来一篇技术文章 - Retrofit2的源码解析。“龙大湿”原名邵震,是Square的一名staff engineer(就是比高级工程师更高一级)。Square公司一直以工程技术强而出名,在开源社区一直有不小的贡献。

  今天,我们就来分析一下Android界Square贡献的四大神器之一的 Retrofit,而且是 2.0。各位怕不怕呀?:D

  文章的作者是峰瑞资本技术团队的Android小牛同学 “大白”,他身高八尺,腰围也是八尺!我们有幸拥有这么一位猛将兄,实属幸运。另外文章又小魔王同学修改和润色,希望大家能喜欢。

  我觉得Retrofit 无疑是这几个当中最好用的一个,设计这个库的思路很特别而且巧妙。Retrofit的代码很少,花点时间读它的源码肯定会收获很多。

  本文的源码分析基于 Retrofit 2(不是1),和Retrofit 1.0的Api有较大的不同。Retrofit2 是retrofit的一次非常大的升级,所以值得深度分析一下。本文分为4个部分,菲娱国际娱乐代理读完并且理解大约花费15分钟。

  首先解释Retrofit这个单词的含义。小魔王惭愧,之前去美国之前虽然考过G、T,但是仍然不认识这个单词。直到在一个老美同事一直在那里说retrofit来retrofit去的时候,我才硬着头皮去查这个单词,后来发现一个单词有着非常正面的含义:“在原基础上翻新改进”。

  简单的说它是一个基于OkHttp的RESTFUL Api请求工具,从功能上来说和Google的Volley功能上很相似,但是使用上很不相似。

  Volley使用上更加原始而且符合使用者的直觉,当App要发送一个Http请求时,你需要先创建一个Request对象,指定这个Request用的是GET、POST或其他方法,一个api 地址,一个处理response的回调;

  如果是一个POST请求,那么你还需要给这个Request对象设置一个body,有时候你还需要自定义添加Header什么的,然后将这个Request对象添加到RequestQueue中,接下去检查Cache以及发送Http请求的事情,Volley会帮你处理。

  而Retrofit可以让你简单到调用一个Java方法的方式去请求一个api,这样App中的代码就会很简洁,方便阅读。

  enqueue方法是异步发送http请求的,如果你想用同步的方式发送可以使用execute()方法,call对象还提供cancel()、isCancel()等方法获取这个Http请求的状态:

  看到没,Retrofit只要创建一个接口来描述Http请求,然后可以让我们可以像调用Java方法一样请求一个Api,菲娱国际登陆是不是觉得很神奇,很不可思议!!

  从上面Retrofit的使用来看,Retrofit就是充当了一个适配器(Adapter)的角色:将一个Java接口翻译成一个Http请求,然后用OkHttp去发送这个请求。

  Volley描述一个HTTP请求是需要创建一个Request对象,而执行这个请求呢,就是把这个请求对象放到一个队列中,在网络线程中用HttpUrlConnection去请求。

  我给Retrofit对象传了一个ZhuanLanApi接口的Class对象,怎么又返回一个ZhuanLanApi对象呢?进入create方法一看,没几行代码,但是我觉得这几行代码就是Retrofit的精妙的地方:

  看Retrofit代码之前我知道Java动态代理是一个很重要的东西,比如在Spring框架里大量的用到,但是它有什么用呢?

  Java动态代理就是给了程序员一种可能:当你要调用某个Class的方法前或后,插入你想要执行的代码。

  比如你要执行某个操作前,你必须要判断这个用户是否登录,或者你在付款前,你需要判断这个人的账户中存在这么多钱。这么简单的一句话,我相信可以把一个不懂技术的人也讲明白Java动态代理是什么东西了。

  上面api对象其实是一个动态代理对象,并不是一个真正的ZhuanLanApi接口的implements产生的对象。

  ServiceMethod就像是一个中央处理器,传入Retrofit对象和Method对象,调用各个接口和解析器,最终生成一个Request,包含api 的域名、path、http请求方法、请求头、是否有body、是否是multipart等等。

  使用Java动态代理的目的就要拦截被调用的Java方法,然后解析这个Java方法的注解,最后生成Request由OkHttp发送。

  余下的retrofit2包中几个类和接口就是全部retrofit的代码了,代码真的很少,很简单,因为retrofit把网络请求这部分功能全部交给了OkHttp了。

  Retrofit的设计非常插件化而且轻量级,真的是非常高内聚而且低耦合,这个和它的接口设计有关。Retrofit中定义了4个接口:

  这个接口主要的作用就是将HTTP返回的数据解析成Java对象,主要有Xml、Gson、protobuf等等,你可以在创建Retrofit对象时添加你需要使用的Converter实现(看上面创建Retrofit对象的代码)。

  这个接口主要的作用就是发送一个HTTP请求,Retrofit默认的实现是OkHttpCallT,你可以根据实际情况实现你自己的Call类。

  这个设计和Volley的HttpStack接口设计的思想非常相似,子类可以实现基于HttpClient或HttpUrlConnetction的HTTP请求工具,这种设计非常的插件化,而且灵活。

  这个方法的主要作用就是将Call对象转换成另一个对象,可能是为了支持RxJava才设计这个类的吧。

  上面api对象其实是一个动态代理对象,并不是一个真正的ZhuanLanApi接口的implements产生的对象。

  刚才说到,ServiceMethod就像是一个中央处理器,具体来看一下创建这个ServiceMethod的过程是怎么样的。

  第二步,解析Method的注解,主要就是获取Http请求的方法,比如是GET还是POST还是其他形式,如果没有,程序就会报错,还会做一系列的检查,比如如果在方法上注解了@Multipart,但是Http请求方法是GET,同样也会报错。

  第三步,比如上面api中带有一个参数{user},这是一个占位符,而真实的参数值在Java方法中传入,那么Retrofit会使用一个ParameterHandler来进行替换:

  上面代码创建了一个Retrofit对象,支持Proto和Gson两种数据格式,并且还支持RxJava。

  Retrofit非常巧妙的用注解来描述一个HTTP请求,将一个HTTP请求抽象成一个Java接口,然后用了Java动态代理的方式,动态的将这个接口的注解“翻译”成一个HTTP请求,最后再执行这个HTTP请求。

  Retrofit的功能非常多的依赖Java反射,代码中其实还有很多细节,比如异常的捕获、抛出和处理,大量的Factory设计模式(为什么要这么多使用Factory模式?)

  Retrofit中接口设计的恰到好处,在你创建Retrofit对象时,让你有更多更灵活的方式去处理你的需求,比如使用不同的Converter、使用不同的CallAdapter,这也就提供了你使用RxJava来调用Retrofit的可能。

  我也慢慢看了Picasso和Retrofit的代码了,收获还是很多的,也更加深入的理解面向接口的编程方法,这个写代码就是好的代码就是依赖接口而不是实现最好的例子。

  好感谢开源的世界,让我能读到大牛的代码。我一直觉得一个人如果没有读过好的代码是不太可能写出好代码的。什么是好的代码?像Picasso和Retrofit这样的就是好的代码,扩展性强、低耦合、插件化。

sitemap sitemap