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 就是根据配置进行工具组装,组装完毕,请求到解析一整套流程就可以顺利执行了。