引言
在使用Retrofit的时候,我们在通过Builder模式获取到Retrofit对象之后,需要通过create方法来获取到接口对象
public interface Api {
@GET("api/data/福利/{pageCount}/{pageIndex}")
Call<BaseModel<ArrayList<Benefit>>> defaultBenefits(
@Path("pageCount") int pageCount,
@Path("pageIndex") int pageIndex
);
@GET("api/data/福利/{pageCount}/{pageIndex}")
Observable<BaseModel<ArrayList<Benefit>>> rxBenefits(
@Path("pageCount") int pageCount,
@Path("pageIndex") int pageIndex
);
}
Api api = retrofit.create(Api.class);
如果仔细一看好像不对啊,为什么接口没有实现,就获取到实例了呢?那么retrofit如何实现我们指定接口的实例呢?
其实原理是:动态代理。
初始动态代理
动态代理是代理模式中的一种,动态代理也算是java的一个特色。
Java动态代理类位于Java.lang.reflect包下,一般主要涉及到以下两个类:
Interface InvocationHandler:该接口中仅定义了一个方法Object:invoke(Object obj,Method method,Object[] args)。在实际使用时,第一个参数obj一般是指代理类,method是被代理的方法,args为该方法的参数数组。这个抽象方法在代理类中动态实现。
Proxy:该类即为动态代理类。
我们先看一个例子,来对动态代理有一个简单的了解
public interface IAPI {
@Deprecated
public void getData(int pageCount, int pageIndex);
}
public static void main(String[] args) {
IAPI iApi = (IAPI) Proxy.newProxyInstance(IAPI.class.getClassLoader(), new Class<?>[]{IAPI.class}, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
Integer pageCount = (Integer) args[0];
Integer pageIndex = (Integer) args[1];
System.out.println("参数: " + pageCount + "," + pageIndex);
System.out.println("方法名: " + method.getName());
Annotation[] annotations = method.getAnnotations();
System.out.println("注解:" + annotations[0].toString());
return null;
}
});
iApi.getData(5, 8);
}
// 打印结果
参数: 5,8
方法名: getData
注解:@java.lang.Deprecated()
可以看出,我们通过Proxy.newProxyInstance产生的代理类,当调用接口的方法时,都会调用InvocationHandler#invoke方法,在这个方法中可以获取到传入的参数和注解,以及方法名等信息。
同理,retrofit同样可以通过这种动态代理的方法,获取到接口里的注解信息,参数。
Retrofit中的动态代理
通过观察也就很容易理解,retrofit是如何为我们接口生成实例的了。
相关参考链接
Retrofit2 完全解析 探索与okhttp之间的关系
别人家SDK中的设计模式--Android Retrofit库源码解读
Retrofit分析-漂亮的解耦套路
独特的架构方式,Retrofit源码简析。