介绍
Retrofit是什么
retrofit:改进、翻新的意思。
Square 公司著名的开源项目之一。
Retrofit这个项目是一个 RESTful 的 HTTP 网络请求框架的封装。
为什么说它使网络请求框架的封装?
主要原因在于网络请求的工作并不是 Retrofit 来完成的
Retrofit 2.0 开始内置 OkHttp,前者专注于接口的封装,后者专注于网络请求的高效,二者分工协作。
我们的应用程序通过 Retrofit 请求网络,实际上是使用 Retrofit 接口层封装请求参数、Header、Url 等信息,之后由 OkHttp 完成后续的请求操作;在服务端返回数据之后,OkHttp 将原始的结果交给 Retrofit,后者根据用户的需求对结果进行解析的过程。
所以说,所谓 Retrofit,其实就是 Retrofitting OkHttp 。
使用
原理解析
Retrofit这个框架的实现主要使用了哪些技术呢?
我觉得核心的就两个:动态代理、注解
-
动态代理
动态代理可以理解成是双层静态代理,表面是A代理了B,其实是A将调用转发给C,C再将调用转发给B。
开发者需要提供一个实现了InvocationHandler的子类 C。用户直接调用代理类 A 的对象,A 将调用转发给委托类 C,委托类 C 再将调用转发给它的委托类 B。
举个栗子
public class Main {
public static void main(String[] args) {
// create proxy instance
TimingInvocationHandler timingInvocationHandler = new TimingInvocationHandler(new OperateImpl());
Operate operate = (Operate)(Proxy.newProxyInstance(Operate.class.getClassLoader(), new Class[] {Operate.class}, timingInvocationHandler));
// call method of proxy instance
operate.operateMethod1();
System.out.println();
operate.operateMethod2();
System.out.println();
operate.operateMethod3();
}
}
A:Porxy.newProxyInstance()生成的代理类
C:TimingInvocationHandler对象
B:OperateImpl对象
使用动态代理的关键就是中间的C,like this
public class TimingInvocationHandler implements InvocationHandler {
private Object target;
public TimingInvocationHandler() {}
public TimingInvocationHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
long start = System.currentTimeMillis();
Object obj = method.invoke(target, args);
System.out.println(method.getName() + " cost time is:" + (System.currentTimeMillis() - start));
return obj;
}
}
proxy:通过 Proxy.newProxyInstance() 生成的代理类对象
method:代理对象被调用的函数
args:表示代理对象被调用的函数的参数。
被代理的类(即委托类)以及相应的接口
public interface Operate {
public void operateMethod1();
public void operateMethod2();
public void operateMethod3();
}
public class OperateImpl implements Operate {
@Override
public void operateMethod1() {
System.out.println("Invoke operateMethod1");
sleep(110);
}
@Override
public void operateMethod2() {
System.out.println("Invoke operateMethod2");
sleep(120);
}
@Override
public void operateMethod3() {
System.out.println("Invoke operateMethod3");
sleep(130);
}
private static void sleep(long millSeconds) {
try {
Thread.sleep(millSeconds);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
- 注解
不说了
好,现在进入正题,关于Retrofit的原理解析
Retrofit对象的create()方法,其内部实现就是通过Porxy.newProxyInstance()来创建代理对象
作者:腾讯Bugly
链接:https://zhuanlan.zhihu.com/p/24109629
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
public <T> T create(final Class<T> service) {
Utils.validateServiceInterface(service);
if (validateEagerly) {
eagerlyValidateMethods(service);
}
//这里返回一个 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, 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);
}
//DefaultMethod 是 Java 8 的概念,是定义在 interface 当中的有实现的方法
if (platform.isDefaultMethod(method)) {
return platform.invokeDefaultMethod(method, service, proxy, args);
}
//每一个接口最终实例化成一个 ServiceMethod,并且会缓存
ServiceMethod serviceMethod = loadServiceMethod(method);
//由此可见 Retrofit 与 OkHttp 完全耦合,不可分割
OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
//下面这一句当中会发起请求,并解析服务端返回的结果
return serviceMethod.callAdapter.adapt(okHttpCall);
}
});
之后,就可以在代理对象身上去调用的接口定义的那些方法了。
都知道,代理对象可以对原本委托对象的方法进行增强,附加更多的功能。
而对于Retrofit来讲,代理对象就是给原本委托对象中相应的方法增加网络请求获取的功能,这个功能具体由谁来做呢,由OkHttp来做。
我们已经看到 Retrofit 为我们构造了一个 OkHttpCall ,实际上每一个 OkHttpCall 都对应于一个请求,它主要完成最基础的网络请求,而我们在接口的返回中看到的 Call 默认情况下就是 OkHttpCall 了,如果我们添加了自定义的 callAdapter,那么它就会将 OkHttp 适配成我们需要的返回值,并返回给我们。