一.Retrofit介绍
我们都知道,Retrofit的定义是
Retrofit是一个RESTful的HTTP网络请求框架的封装,网络请求的工作本质上是OkHttp完成,而Retrofit仅负责网络请求接口的封装
App应用程序通过Retrofit请求网络,实际上是使用Retrofit接口层封装请求参数,之后由OkHttp完成后续的请求操作;服务器数据返回后,OkHttp将原始的结果交给Retrofit,根据用户需求对结果进行解析;
那么什么是rest规范呢?
1.rest规范
rest即Representational State Transfer,翻译过来就是资源表现层状态转换。下面我说下我对这个规范的理解
资源:一个URI代表一个资源,比如是一个文本,一个图片等。
表现层:即资源的表现形式,比如文本可以用txt形式表现,图片可以用jpg,png形式表现。
状态转换:即将资源的状态进行转换,比如得到资源,更改资源,删除资源等,对应HTTP四个方法,即GET,POST,PUT,DELETE
。
它有两个非常值得注意的点
①第一个就是,URI中不应该包括动词(最常见的URI就是URL)。比如
错误写法 | 正确写法 |
---|---|
https://localhost:8080/myweb/getDogs | GET /rest/api/dogs(获取所有小狗狗) |
https://localhost:8080/myweb/addDogs | POST /rest/api/dogs(添加一个小狗狗) |
https://localhost:8080/myweb/updateDogs/:dog_id | PUT /rest/api/dogs/:dog_id(修改一个小狗狗) |
https://localhost:8080/myweb/deleteDogs/:dog_id | DELETE /rest/api/dogs/:dog_id(删除一个小狗狗) |
②第二个就是,无状态。
即所有的资源都可以通过URI定位,而不是知道前面的才知道后面的(RxJava的响应式编程就是知道前面的才能干后面的)。如果是有状态的,则后面的操作依赖于上一步的结果。如果是无状态的,则可以直接进行后面的操作。比如查工资,如果是有状态,则需要先登录系统,然后点击这个,然后再点击那个。。。如果是无状态,则可以直接查询工资。
2.基本使用
基本使用很简单,我在这一篇文章中有写到,需要注意的一点是,RxJava的返回值是Observable
类型,而传统的Retrofit的返回值是Call
类型
报错1:IllegalArgumentException: Unable to create call adapter for io.reactivex.Observable<com.example.retrofittest.bean.Project
解决方案
报错2: java.lang.IllegalStateException: Already executed.
解决方案
需要整理一下的是它的注解:好文章推荐
在这里说下它比较常见的,一个是Path
,可以理解为替换
一个是Query
,可以理解为键值对,但是它是在GET
的时候用
一个是Field
,也可以理解为键值对,但是它在POST
的时候用
其他的像GET,POST,PUT,DELETE
就分别对应HTTP的四种动作。
二.执行时,源码的总体流程
这里我推荐这一篇文章
1.Retrofit 的请求流程
我把请求流程搬到这里来,方便后面复习
我们在调用 Service
接口的 请求网络的方法时,会调用 InvocationHandler
的 invoke
方法(动态代理)
然后执行 loadServiceMethod
方法并返回一个 HttpServiceMethod
对象并调用它的 invoke
方法
然后执行 OkHttpCall
的 enqueue
方法(OkHttpCall
就是在Service
接口中方法的返回值类型的对象)
本质执行的是 okhttp3.Call
的 enqueue
方法
当然这期间会解析方法上的注解,方法的参数注解,拼成 okhttp3.Call
需要的 okhttp3.Request
对象
然后通过Converter
来解析返回的响应数据,并回调 CallBack
接口
Retrofit中动态代理的目的:InvocationHandler
的 invoke
方法中拦截到了我们的方法,参数等信息。Retrofit 的原理其实就是这样,拦截到方法、参数,再根据我们在方法上的注解,去拼接为一个正常的OkHttp 请求,然后执行。也就是做一个统一的拦截。
2.注解的解析流程
在 ServiceMethod.parseAnnotations(this, method);
方法中开始的
具体内容是在 RequestFactory
类中,进行解析注解的
调用 RequestFactory.parseAnnotations(retrofit, method);
方法实现的
3.Converter 的转换过程,怎么通过 Gson 转成对应的数据模型的?
通过成功回调的 parseResponse(rawResponse);
方法开始
通过 responseConverter
的 convert
方法
responseConverter
是通过 converterFactories
通过遍历,根据返回值类型来使用对应的 Converter
解析
4.CallAdapter 的替换过程,怎么转成 RxJava 进行操作的?
通过配置 addCallAdapterFactory(RxJava2CallAdapterFactory.create())
在 callAdapterFactories
这个 list
中添加 RxJava2CallAdapterFactory
如果不是 Kotlin 挂起函数最终调用的是 CallAdapter
的 adapt
方法
callAdapter
的实例是通过 callAdapterFactories
这个 list
通过遍历,根据返回值类型来选择合适的CallAdapter
三.Retrofit的设计模式
这里我推荐这一篇文章
搬运一下
首先retrofit本身就是一个门面/外观模式,它的构建是建造者模式(Retrofit类就是Retrofit框架提供给我们的外观类),
同时还可以add
各种各样的工厂,是策略模式,add
方法里面的参数用到了工厂模式
还有适配器模式,比如用Gson适配返回的数据
他的create
方法用到了代理模式,而且是动态代理
还用到了装饰者模式,ExecuteCallBack
使用装饰者模式来封装callbackExecutor
,用于完成线程的切换
还用到了静态代理模式。(ExecutorCallbackCall
是代理,而里面真正去执行网络请求的还是OkHttpCall
)
他的网络请求,用到了观察者模式,call
是被观察者,CallBack
是观察者