Android中Retrofit原理解析

347 阅读5分钟

1,Retrofit介绍

Retrofit是一个RESTFUL的Http网络请求的封装,网络请求的本质还是OkHttp来完成的,Retrofit只负责网络请求接口的封装。

OkHttp使用中的缺陷:

1,用户网络请求接口配置繁琐,尤其是需要配置复杂请求body、请求头、参数的时候

2,数据解析过程中需要用户手动拿到responsBody进行解析,不能复用

3,无法适配自动进行线程切换

4,万一存在嵌套网络请求,就会陷入回调陷阱

App应用程序通过Retrofit请求网络,实际上是使用Retrofit接口层封装请求参数、header、url等信息,之后再交由OkHttp完成后续的请求操作

在服务器端返回数据之后,由OkHttp将原始请求的结果交由Retrofit,Retrofit根据用户的需求进行数据的解析,retrofit本身是一个门面或者外观模式

 1,对网络请求参数的适配,通过注解,协议表单
 2,封装Okhttp call
 3,返回数据结构的封装

2,Retrofit设计的目的

请求前:统一配置请求头、一致适配请求的Request(XXXService mXXXService = retrofit.create(XXXService.class))

结束后:线程的切换、数据的适配

Retrofit用注解、代理、反射通过一系列设计模式对OkHttp进行请求前的封装

3,Retrofit封装的分类

Build模式 创建网络请求的基本配置

用注解来排列组合成网络请求(Retrofit中注解的类型,请求方法,请求标注,请求参数)

统一提供Gson解析 提供了可复用,易扩展的数据解析方案

自定义callBackExcutor(handler)完成线程的切换

4,Retrofit实例创建过程

创建实例的过程使用了构建者模式和外观模式(门面模式:对外展示的统一门道) 4个及以上参数并且参数可选可使用构建者模式

QQ截图20230128103708.png

微信截图_20230313113240.png

Call xxxBean = XXXService.getSharedList(2,1)

调用getSharedList的时候,在动态代理里面,会存在一个getShareList函数,这个函数会调用invoke,这个invoke就是retrofit里面的invoke函数,所以动态代理可以代理所有的接口,让所有的接口都走invoke函数,这样就可以拦截函数的执行,从而将网络请求的参数归一化。

微信截图_20230313120437.png

微信截图_20230313120537.png

5,Retrofit的统一配置网络请求头和适配请求的request

代理类和委托类有同样的接口

代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类、以及事后处理消息等

一个代理类的对象和委托类的对象关联,代理类的对象本身并不真正实现服务,而是调用委托类的相关方法,来提供特定的服务。

动态代理

QQ截图20230128120913.png

XXXService mXXXService = retrofit.create(XXXService.class) 创建了一个XXXService的接口类对象,create函数内部使用了动态代理来创建接口对象,这样的设计可以让所有的访问请求被代理

在create方法中会去转到retrofit的动态代理类中的invoke函数,invoke函数中的参数method就是实现了XXXService中的接口,拿到method之后就意味着拿到了接口,就可以根据接口上面的注解去解析接口,接口上注解 + baseUrl + 参数 解析成了一个OkHttp需要的request()

在retrofit的creat方法中:ServiceMethod serviceMethod = loadServiceMethod(method)

loadServiceMethod会通过一个构建者模式,构建出一个ServiceMethod对象,构建ServiceMethod的过程就是把参数变成request()的过程,ServiceMethod对象包含retrofit对象、方法上的注解、执行这个请求的参数类型、参数的注解,ServiceMethod中大量使用反射,一般反射比较耗性能,在ServiceMethod的build中使用了serviceMethodCache缓存了起来,避免了性能大量损耗

QQ截图20230128121134.png

QQ截图20230128120658.png

6,Retrofit中的线程切换和数据适配

进行网络请求时:retrofit.creat()在OkHttp的call中再次包装了一次,先去执行了ExcutorCallBackCall中的enqueue(CallBack callBack),ExcutorBackCall中的enqueue方法中会去执行OkHttp的enqueue

QQ截图20230128141010.png

7,Retrofit中的设计模式

1,Retrofit的实例使用了**建造者模式**通过Builder类构建,当构造函数的参数大于4个,并且参数可选的时候,可以使用建造者设计模式

2,Retrofit创建的callFactory,使用工厂方法设计模式,但似乎并不打算支持其他工厂

3,整个Retrofit采用的是**外观设计模式**,统一的调用创建网络请求接口实例和网络请求参数的配置方法

4,Retrofit里面使用了动态代理的方式创建网络接口的实例,这是Retrofit对于用户使用来说最大的复用,其他代码都是支持这个动态代理给用户带来便捷性

5,使用了策略模式对于ServiceMethod对象进行网络请求参数的配置,即通过解析网络请求参数,返回值和注解类型,从Retrofit对象中获取网络请求的Url地址,网络请求执行器,网络请求适配器和数据转换器

6,ExcuterCallBack使用了**装饰者模式**来封装callBackExcuter,用于完成线程的切换

7,ExcutorCallBackCall使用了静态代理(委托)代理了call进行网络请求,真正的网络请求okHttpCall执行,然后okhttpcall不是自己执行,它是okhttpcall提供call给外界(retrofit)使用的唯一门户,这个地方就是**门面模式**

8,ExcutorCallBackCall的初始化是在ExcutorCallAdapterFactory里面通过**适配器模式**被创建,CallAdater采用了**适配器模式**为创建访问接口提供服务,默认不添加Rxjava则使用默认的ExcutorCallAdapterFactory将Okhttp3.call转变为retrofit中的call,如果有Rxjava则将Okhttp3.call转变为Observable