美文网首页Android开发Android开发经验谈Android进阶之路
Android高频面试专题 - 架构篇(三)Retrofit

Android高频面试专题 - 架构篇(三)Retrofit

作者: Android扫地僧 | 来源:发表于2020-03-16 18:29 被阅读0次

    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开发面试专题资料,高级进阶架构资料这些都是我闲暇还会反复翻阅的精品资料。在脑图中,每个知识点专题都配有相对应的实战项目,可以有效的帮助大家掌握知识点

    总之也是在这里帮助大家学习提升进阶,也节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习

    image

    关注微信公众号“Android扫地僧”
    发送【资源】自动回复,即可获取下载地址

    image

    相关文章

      网友评论

        本文标题:Android高频面试专题 - 架构篇(三)Retrofit

        本文链接:https://www.haomeiwen.com/subject/jhznehtx.html