Retrofit并不是网络请求框架,严格说只是对网络请求的一种封装,我们只需要定义一个接口类,在请求方法上加上相应的注解,甚至都不需要实现,就可以实现网络请求。但面试可就不只是要求会使用了,咱得知道内部是怎么实现的,才能顺利过关。
本篇内容,只是作为面试,提炼一下要点,建议还是先熟悉一下Retrofit的整个源码流程。关于retrofit完整源码解析,请回复【框架解析】获取视频讲解。
1、静态代理和动态代理
提到这个是因为,retrofit的精髓就在于内部的动态代理模式。
Java中的静态代理要求代理类(ProxySubject)和委托类(RealSubject)都实现同一个接口(Subject)。静态代理中代理类在编译期就已经确定,而动态代理则是JVM运行时动态生成,静态代理的效率相对动态代理来说相对高一些,但是静态代理代码冗余大,一旦需要修改接口,代理类和委托类都需要修改。
动态代理的两种实现方式:
JDK自带的java.lang.reflect.Proxy,只能代理接口类
CGLib,生产子类来实现方法增强,无需实现接口
Retrofit使用的就是JDK的动态代理。
2、简单介绍下retrofit实现原理
首先,通过Builder创建Retrofit对象,在create方法中,通过JDK动态代理的方式,生成实现类,在调用接口方法时,会触发InvocationHandler的invoke方法,将接口的空方法转换成ServiceMethid, 然后生成okhttp请求,通过callAdapterFactory找到对应的执行器,比如RxJava2CallAdapterFactory,最后通过ConverterFactory将返回数据解析成JavaBena,使用者只需要关心请求参数,内部实现由retrofit封装完成,底层请求还是基于okhttp实现的。
3、Retrofit关键类
Retrofit源码非常简练,关键类就看类成员变量,就只有下面7个。
public final class Retrofit {
private final Map<Method, ServiceMethod<?, ?>> serviceMethodCache = new ConcurrentHashMap<>();
final okhttp3.Call.Factory callFactory;
final HttpUrl baseUrl;
final List<Converter.Factory> converterFactories;
final List<CallAdapter.Factory> callAdapterFactories;
final @Nullable Executor callbackExecutor;
final boolean validateEagerly;
....
}
ServiceMethod
核心处理类,解析接口中定义的请求方法参数和注解,通过toCall方法将其转换成okhttp的call对象,有了Call对象,就可以发送请求了。
callFactory
字面意思就是生产Call的工厂,这里的Call是okhttp包下面的Call,CallFactory默认就是OkHttpClient
HttpUrl
就是将创建retrofit对象时传入的baseUrl转换成对象,进行格式校验等。
converterFactories
数据解析器Converter,将response通过converterFactory转换成对应的JavaBean数据形式,常见解析器有,GsonConverterFactory,FastJsonConverterFactory,当然也有xml的。
callAdapterFactories
通过calladapter将原始Call进行封装,找到对应的执行器。如rxjavaCallFactory对应的Observable,转换形式Call<T> --> Observable<T>
callbackExecutor
主线程执行器,返回结果在UI线程执行
validateEagerly
是否立即校验所以接口方法,也就是将接口类中的方法全部转换成ServiceMethod,默认为false
4、注解相关
定义一个注解:
@Documented //该注解类应该被javadoc工具记录
@Target(METHOD) //注解使用的地方
@Retention(RUNTIME) //注解保留期限
public @interface GET {
String value() default ""; //注解参数
}
@Documented
表示该注解类会被收录进JavaDoc,不影响运行
@Target
表示注解要使用的地方,比如@Target(METHOD)用在方法上,@Target(TYPE)用在类/接口上,@Target(FIELD)用在成员变量上
@Retention
注解保留期限,@Retention(SOURCE)在源文件有效,@Retention(CLASS)在class文件中有效,@Retention(RUNTIME)在运行期有效
注解的使用
使用反射在运行时获取注解,进行业务逻辑处理
通过预编译工具进行处理(pre-compiler tools),在编译期间生成新的类文件
5、retrofit多个BaseUrl如何解决
根据不同BaseUrl创建不同的Retrofit对象(不可取)
@GET、@POST、@Url不仅可以传相对路径,也可以传绝对路径
大神JessYan的方案https://www.jianshu.com/p/2919bdb8d09a
在这我也分享一份自己收录整理的Android学习PDF+架构视频+面试文档+源码笔记,还有高级架构技术进阶脑图、Android开发面试专题资料,高级进阶架构资料这些都是我闲暇还会反复翻阅的精品资料。在脑图中,每个知识点专题都配有相对应的实战项目,可以有效的帮助大家掌握知识点
总之也是在这里帮助大家学习提升进阶,也节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习
imageimage关注微信公众号“Android扫地僧”
发送【资源】自动回复,即可获取下载地址
网友评论