Retrofit分析-漂亮的解耦套路
万万没想到Retrofit会这么火,在没看源码之前,我简单的认为是因为它跟OkHttp同出一源(Square),所以才会炒的那么热。又或者是因为它能支持RxJava,所以火上浇油,一发不可收拾。
后来看过Retrofit源码之后,我才理解为什么它倍受关注,是因为它集诸优点于一身,并且炒鸡解耦。你能预见的特殊需求,都能非常容易的扩展。
没有HTTP框架的日子
我们先来看一下没有HTTP框架以前,我们是如何做请求的。
![](http://upload-images.jianshu.io/upload_images/625299-e0f8fda2d0855996.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/862/format/webp)
- 首先build request参数
- 因为不能在主线程请求HTTP,所以你得有个Executer或者线程
- enqueue后,通过线程去run你的请求
- 得到服务器数据后,callback回调给你的上层。
大概是以上4大步骤,在没有框架的年代,想要做一次请求,是万分痛苦的,你需要自己管理线程切换,需要自己解析读取数据,解析数据成对象,切换回主线程,回调给上层。
这段空白的时间持续了很久。从我10年工作起到12年,因为写烦了重复的代码,所以就得想办法,把那些变化的地方封装起来,也只是简单的封装。好在官方出了AsyncTask,虽然坑很多,但如果再自己维护一个队列,基本不会出现问题。更好的地方是数据格式从xml变成json了。gson解放了双手,再也不用解析dom了。
早些时期的HTTP框架
后来慢慢出了不少真正的HTTP框架。Stay也借鉴了很多文章,封装了一套适用于自身业务需求的框架。
这个时期的框架有个特点,就是拼了命去支持所有类型。比方说Volley支持直接返回Bitmap。xUtils不仅大而全,而且连多线程下载也要支持。在资源匮乏的时代,它们的存在有它们的道理。但如果说现在还用Volley做图片请求,还在用xUtils或Afinal里的各个模块。那就说不过去了。术业有专攻,百家争鸣的时期,难道不该选择最好的那一个吗?(Stay没真的用过xUtils和Afinal这种组合框架,潜意识告诉我,它们有毒,一旦某个环节出问题或者需要扩展,那代价就太大了)
Retrofit
好吧,介绍完HTTP框架的发展,让我们单纯的说说Retrofit吧。
tips:本文以retrofit最新版本2.0.1为例,大家也可以去github下源码,找tag为'parent-2.0.1'就可以。目前代码变动比较大。2.0.1已经使用okhttp3了,而我项目中2.0.0-beta2还是okhttp2.5。
retrofit的最大特点就是解耦,要解耦就需要大量的设计模式,假如一点设计模式都不懂的人,可能很难看懂retrofit。
先来看一张Stay画的精简流程图(如有错误,请斧正),类图就不画了。
![](http://upload-images.jianshu.io/upload_images/625299-29a632638d9f518f.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/891/format/webp)
Stay在一些设计模式很明确的地方做了标记。
外观模式,动态代理,策略模式,观察者模式。当然还有Builder模式,工厂等这些简单的我就没标。
先简述下流程吧:
通过门面Retrofit来build一个Service Interface的proxy
retrofit03.png- 当你调用这个Service Interface中的某个请求方法,会被proxy拦截。
retrofit02.png
通过ServiceMethod来解析invoke的那个方法 ,通过解析注解,传参,将它们封装成我们所熟悉的request。然后通过具体的返回值类型,让之前配置的工厂生成具体的CallAdapter,ResponseConverter,这俩我们稍后再解释。
new一个OkHttpCall,这个OkHttpCall算是OkHttp的包装类,用它跟OkHttp对接,所有OkHttp需要的参数都可以看这个类。当然也还是可以扩展一个新的Call的,比如HttpUrlConnectionCall。但是有点耦合。看下图标注:
retrofit031.png红框中显式的指明了OkHttpCall,而不是通过工厂来生成Call。所以如果你不想改源码,重新编译,那你就只能使用OkHttp了。不过这不碍事。(可能也是因为还在持续更新中,所以这块可能后面会改进的)
生成的CallAdapter有四个工厂,分别对应不同的平台,RxJava, Java8, Guava还有一个Retrofit默认的。这个CallAdapter不太好用中文解释。简单来说就是用来将Call转成T的一个策略。因为这里具体请求是耗时操作,所以你需要CallAdapter去管理线程。怎么管理,继续往下看。
比如RxJava会根据调用方法的返回值,如Response<'T> |Result<'T>|Observable<'T> ,生成不同的CallAdapter。实际上就是对RxJava的回调方式做封装。比如将response再拆解为success和error等。(这块还是需要在了解RxJava的基础上去理解,以后有时间可以再详细做分析)
在步骤5中,我们说CallAdapter还管理线程。比方说RxJava,我们知道,它最大的优点可以指定方法在什么线程下执行。如图
retrofit04.png我们在子线程订阅(subscribeOn),在主线程观察(observeOn)。具体它是如何做的呢。我们看下源码。
retrofit05.png在adapt Call时,subscribeOn了,所以就切换到子线程中了。
在adapt Call中,具体的调用了Call execute(),execute()是同步的,enqueue()是异步的。因为RxJava已经切换了线程,所以这里用同步方法execute()。
retrofit06.png接下来的具体请求,就是OkHttp的事情了,retrofit要做成的就是等待返回值。在步骤4中,我们说OkHttpCall是OkHttp的包装类,所以将OkHttp的response转换成我们要的T,也是在OkHttpCall中执行的。
当然具体的解析转换操作也不是OkHttpCall来做的,因为它也不知道数据格式是什么样的。所以它只是将response包装成retrofit标准下的response。
Converter->ResponseConverter,很明显,它是数据转换器。它将response转换成我们具体想要的T。Retrofit提供了很多converter factory。比如Gson,Jackson,xml,protobuff等等。你需要什么,就配置什么工厂。在Service方法上声明泛型具体类型就可以了。
最后,通过声明的observeOn线程回调给上层。这样上层就拿到了最终结果。至于结果再如何处理,那就是上层的事了。
再来回顾下Stay画的流程图:
![](http://upload-images.jianshu.io/upload_images/625299-29a632638d9f518f.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/891/format/webp)
这真是漫长的旅行,Stay也是debug一个个单步调试才梳理出来的流程。当然其中还有很多巧妙的解耦方式,我这里就不赘述了。大家可以看看源码分析下,当真是设计模式的经典示例。
我想现在大家应该对retrofit有所了解了。当你再给别人介绍retrofit的时候,就别只说它的注解方式多新颖,多炫技了。注解式框架有很多的,像j2ee中一大把。所以注解算不得多精湛的技艺。最牛逼的还是它的解耦方式,这个套路没有多年的实际架构经验是设计不出来的。
扩展阅读:
OkHttp, Retrofit, Volley应该选择哪一个?
Retrofit分析-谜之槽点
这么多开源框架,该用哪个好?
Retrofit分析-漂亮的解耦套路(视频版)
Retrofit分析-经典设计模式案例
作者:stay4it
链接:https://www.jianshu.com/p/45cb536be2f4
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。
转载于:https://www.cnblogs.com/davidwang456/articles/10937714.html
Retrofit分析-漂亮的解耦套路相关推荐
- cookie代码加时间多久出现一次_恶意代码分析 丨 一个毫无套路的咸鱼诈骗网站...
在一个百无聊赖的周三下午,还有半个钟头就要下班了,这时候赶紧准备一下,工作收收尾,我们的口号是在5点30准时打卡下班.在一切都收拾妥当发现还有20分钟,无聊的打开论坛决定水水贴,然后看到了一篇关于闲鱼 ...
- 数分笔记整理21 - 数据处理项目 - 城市餐饮店铺选址分析 电商打折套路解析
[项目07] 城市餐饮店铺选址分析 ''' [项目07] 城市餐饮店铺选址分析1.从三个维度"口味"."人均消费"."性价比"对不同菜系进行 ...
- 电容电感阻抗模型分析和电源解耦电容选取经验
- RxJava+Retrofit+MVP+Dagger2
传说中的谷歌四件套,按顺序来哈~ 2017.2.20更新:对于用了一段时间的谷歌四件套的开发者们来说,基础应该都已经掌握的差不多了,但是四件套确实很博大精深,要想完全掌握,一是要学习使用技巧,二是要在 ...
- Retrofit 使用详解
转载请标明出处:http://blog.csdn.net/xx326664162/article/details/51910837 文章出自:薛瑄的博客 你也可以查看我的其他同类文章,也会让你有一定的 ...
- 网络加载框架 - Retrofit
Retrofit是什么? Retrofit其实我们可以理解为OkHttp的加强版,它也是一个网络加载框架.底层是使用OKHttp封装的.准确来说,网络请求的工作本质上是OkHttp完成,而 Retro ...
- Android 优秀文章收集整理集合
转载 自 https://github.com/jiang111/awesome-android-tips 记录自己遇到的比较有价值的Android相关的blog MaHua是online md ...
- Android优秀文章收集(转载)
http://blog.csdn.net/u010375364/article/details/52200425 http://blog.csdn.net/u010375364/article/det ...
- 如何通俗理解设计模式及其思想?
本文由玉刚说写作平台提供写作赞助 原作者:却把清梅嗅 版权声明:本文版权归微信公众号玉刚说所有,未经许可,不得以任何形式转载 术与道 数据结构,算法,设计模式被认为是程序员必备技能的三叉戟,如果说编程 ...
最新文章
- mybatis-错误记录java.lang.ExceptionInInitializerError
- 在吗?认识一下JWT(JSON Web Token) ?
- MySQL数据库排序order by(asc、desc)
- 网站优化时不容错过的时期有哪几个?
- 计算几何中的线段相交判断问题
- 指令发送没反应_如何判断网络故障的原因?7个指令,教你逐步排查!
- linux C 进程内部存储管理
- 【Pytorch神经网络理论篇】 26 基于空间域的图卷积GCNs(ConvGNNs):定点域+谱域+图卷积的操作步骤
- 华为服务器双系统教程,服务器上安装双系统
- python---之np.cumprod np.cumsum 累乘 累加
- 6.4 tensorflow2实现FNN推荐系统——Python实战(第二篇)
- 键盘迷情--Treo650 VS P50 【ZZ】
- delphi 读取pdf
- 广工Anyview数据结构习题
- Java学习篇之I/O篇
- c语言三角函数例题,三角函数的诱导公式习题及答案解析.doc
- mysql 超级用户登录_MySQL超级用户(root)密码忘记重置
- 美丽小猪Java基础笔记02【小美女程序猿诞生日记 之 java学习笔记】
- [转]通过研究视线轨迹改良设计
- 网站关键词排名,如何快速提升?
热门文章
- 吴恩达机器学习Ex3作业
- 专插本跨考计算机科学与技术,2021年计算机科学与技术专业-计算机组成原理-考试大纲(专插本).docx...
- leetcode 105. 从前序与中序遍历序列构造二叉树 c语言递归解法
- ug怎么画曲线_UG怎么画雨伞的曲面造型
- 计算机音乐刚好遇见你乐谱,刚好遇见你曲谱_刚好遇见你乐谱
- 计算机控制zos,第二章zOS操作系统的功能概述2.1zOS的内存管理.PDF
- python字典里可以放列表吗_学习python之列表及字典
- 银行家算法的分析与实现
- C语言整数加法器,【菜鸟解析】C++大数加法器的实现
- php判断ip跳转城市,PHP判断IP并转跳到相应城市分站的方法