我们已经知道retrofit的主要作用是把一个接口解析包装成http的请求,由OKhttp发送。用到的技术就是动态代理。动态代理的作用就是当你要调用某个Class的方法前或后,插入你想要执行的代码。接下来我们看一下如何实现动态代理。
一、定义接口:
public interface UserListener {
String getName();
int getAge();
}
二、创建该接口的实现类
public class User implements UserListener {
@Override
public String getName() {
return "哈哈哈";
}
@Override
public int getAge() {
return 18;
}
}
三、创建动态代理类并实现InvocationHandler接口,该接口只包含一个方法,之后再讲解它
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable;
动态代理类:
public class MyInvocationHandler implements InvocationHandler {
private Object target;
public MyInvocationHandler(Object target){
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if(method.getName().equals("getName")){
String result = (String) method.invoke(target,args);
return result+"嘿嘿嘿";
}else {
int age = (int) method.invoke(target,args);
return age+10;
}
}
}
四、使用动态代理类:
UserListener user = new User();
MyInvocationHandler handler = new MyInvocationHandler(user);
UserListener proxy = (UserListener) Proxy.newProxyInstance(user.getClass().getClassLoader(),user.getClass().getInterfaces(),handler);
Log.d("proxy",proxy.getName());
Log.d("proxy",proxy.getAge()+"");
结果:
03-11 13:05:22.631 30332-30332/com.yjs.okhttp D/proxy: 哈哈哈嘿嘿嘿
03-11 13:05:22.641 30332-30332/com.yjs.okhttp D/proxy: 28
解析
首先看一下InvocationHandler中的方法,
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable;
Object proxy:指代我们所代理的那个真实对象
Method method:指代的是我们所要调用真实对象的某个方法的Method对象
Object[] args:指代的是调用真实对象某个方法时接受的参数
接下来再看一下Proxy类中的newProxyInstance方法:
public static Object newProxyInstance(ClassLoader loader,
Class>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
ClassLoader loader:定义了由哪个ClassLoader对象来对生成的代理对象进行加载
Class<?>[] interfaces:一个Interface对象的数组,表示的是我将要给我需要代理的对象提供一组什么接口,如果我提供了一组接口给它,那么这个代理对象就宣称实现了该接口(多态),这样我就能调用这组接口中的方法了
InvocationHandler h:一个InvocationHandler对象,表示的是当我这个动态代理对象在调用方法的时候,会关联到哪一个InvocationHandler对象上
最后看一下Retrofit中的创建方法:
ApiStores apiStores = ApiClient.retrofit().create(ApiStores.class);
public T create(final Class 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, 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 serviceMethod = loadServiceMethod(method);
OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.callAdapter.adapt(okHttpCall);
}
});
}
当我们把包含网络请求接口的类传入到Retrofit的create方法后,就会利用动态代理模式,将接口解析包装成ServiceMethod,再转化成OkHttpCall供OKhttp调用。