欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Retrofit 原理简析

程序员文章站 2022-07-05 10:59:36
...

简介

  Retrofit 所做的事情简单来说就是将你的 Http 业务 API --> Http 请求实现,类似于 Spring MVC 中的 Controller,它的主要任务是解析你的业务接口,从接口上获取你的 Http 接口协议,然后组装 Http 请求,进行异步 Request。
  Retrofit 整合了多个组件,包括 JSON/XML 的 ORM 映射,用于解析返回值;Http请求驱动用语发送 Http 请求,Retrofit 默认使用的是 Okhttp;异步处理框架,包括Observable。

原理

  如何生成一个接口的实现类,除了手动实现该接口之外,还有另外一种选择,那就是动态代理;Retrofit 的核心正是如此。
  如同 SpringMVC 的 Controller 一样,在方法描述上(方法描述包括 Modifiers,参数列表,返回值类型,异常列表),再加上参数列表上的注解,方法体上的注解,通过一个方法的描述就可以基本确定一个 Http 接口的所有协议了。

1. 请 求 目 标 地 址 和 请 求 方 法 :

  通 过 解 析 方 法 体 上 的 注 解 。 类 似 这 种@POST("/mobile/login") 代表请 POST 方法,地址“Domain/mobile/login”。

2.请求参数:

  通过解析参数列表和参数列表上的注解,如(@Query("loginname")StringloginName, @Query("pass")String pass) 代表其有两个参数 loginName,pass。

3. 请求返回值:

  通 过 解 析 方 法 的 返 回 值 类 型 。 例 如Observable<baseresponse> Observable 是异步可观测数据 RxJava 的包裹类,真正的业务 Model 类型在范型里面。

源码分析

  先来看创建 API 代理的入口方法 Retrofit.create(Class class):
public <T> T create(final Class<T> service) {
    Utils.validateServiceInterface(service);
    if (validateEagerly) {
      eagerlyValidateMethods(service);
    }
    return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
        new InvocationHandler() {
          private final Platform platform = Platform.get();

          @Override public Object invoke(Object proxy, Method method, @Nullable Object[] args)
              throws Throwable {
            // If the method is a method from Object then defer to normal invocation.
            if (method.getDeclaringClass() == Object.class) {
              return method.invoke(this, args);
            }
            if (platform.isDefaultMethod(method)) {
              return platform.invokeDefaultMethod(method, service, proxy, args);
            }
            ServiceMethod<Object, Object> serviceMethod =
                (ServiceMethod<Object, Object>) loadServiceMethod(method);
            OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
            return serviceMethod.callAdapter.adapt(okHttpCall);
          }
        });
  }

1.Utils.validateServiceInterface(service):

  检查传进来的 Class 对象是否合法,主要检查两个方面一是 Class 是否是接口,二是接口一定不能继承其他接口。

2.eagerlyValidateMethods(service):

  validateEagerly 这个参数控制了是否是在 create 是提前解析业务接口并且进行缓存,否则的话将需要在业务方法调用时解析。

3.Platform:

  如字面所描述平台类,Retrofit 专门为操作系统运行环境抽象了一层,事实上,Retrofit 可以运行在 Android,IOS,Java8 三个平台上。获取比较诡异的事为什么 Java代码可以在 IOS 平台运行,事实上是借助了一个叫 robovm 的第三方 JVM,Class.forName("org.robovm.apple.foundation.NSOperationQueue"); 这段代码就是获取 robovm 的线程池。Platform 主要提供了异步所需要的线程池,异步同步控制,而这个是一个抽象的接口,在 Retrofit 初始化时是可以指定其实现的。CallAdapter 就是上述接口。

4.invokeDefaultMethod:

  这个对应了 Java8 中 的 default 方 法 , 暂 时 没 有 实 现 , 会 抛 出UnSupportOperationException,也就是说你不可以调用接口中的 default 方法。

5.loadServiceMethod(method):

  加载 API 方法的实现,即加载动态代理,前面说过了,如果在 create 时已经解析过接口了的话,代理对象直接在缓存中找到。如果没有则需要在这个时候解析并且存储到缓存中,下次调用同样的接口就不需要重复解析了,毕竟业务解析大量用到了反射这种耗时操作。

6.ServiceMethod.Build():

  解析业务接口方法并且生成对应的动态代理。
  解析返回值类型: Utils.getRawType 从返回值的范型中扣出真正的业务类型,应为返回值一般不会直接写业务 Model,而是对异步任务的包裹,对 Callback 的封装。
  createResponseConverter 和 parseMethodAnnotation 开始创建 Http 请求,这时候需要解析方法上的 Annotation,这个 Annotation 包含了 URL,和请求方法。获取完了这些信息之后,这个方法就开始根据这些参数拼装完整的 URL。
  parseParameter 解析方法参数 ,获取 请 求 参数 。 这个方法主要就是调用了parseParameterAnnotation 解析参数列表上的注解,注解中包含了参数类型,参数名,Header,Path 等信息。参数类型也可以是 Form,Part 等复杂类型。
  createCallAdapter 上面说过了,Retrofit 只是一个业务解析器,组装器,诸如返回值的 JSON/XML 解析,Http 请求底层等等都是交给其他框架处理的,Adapter 就是抽象接口,createCallAdapter 就是根据配置进行工具组装,组装完毕,请求到解析一整套流程就可以顺利执行了。