参考官方文档:https://square.github.io/retrofit/
马老师教导我们要穿一手鞋,而且官方文档足够的详细。
在我们使用 Retrofit 进行网络请求时,实际其内部使用 OkHttp 来完成网络请求的,然后,使用我们传入的 “类型转换器” 把响应转换成我们指定的类型。定义了一个接口并调用了该接口的方法,然后就拿到了请求的结果,这看上去非常简洁,而这其中的最功不可没的就是动态代理。
代理模式也叫委托模式,是结构型设计模式的一种。在Android中代理模式有很多,如Binder。生活中也有很多代理的例子,例如代购、看国外的风景等。
代理模式结构图:
假设我想看看qiang外的风景,但是门被焊死了,焊门的兄弟临走连窗户也给堵上了,这个时候我就需要一个梯子(因为我不够高)
抽象主题类具有真实主题类和代理的共同接口方法,我想看风景,那么共同的方法就是看风景:
public interface ILadder {
/**
* 看风景
*/
void climbWall();
}
为了能看到腐国的自由女神像,所以搞一个腐国的梯子(AmericaLadder),它还得有看风景的能力:
public class AmericaLadder implements ILadder {
@Override
public void climbWall() {
System.out.print("我看到了自由女神像");
}
}
梯子并不是我的,是我的一个朋友提供给我的,所以我是通过我的朋友得到的这个梯子实现的看风景的能力:
public class MyFriendProxy implements ILadder {
/**
* 朋友的梯子
*/
private ILadder iLadder;
public MyFriendProxy(ILadder iLadder){
this.iLadder=iLadder;
}
@Override
public void climbWall() {
iLadder.climbWall();
}
}
有了梯子,才能看到外面的风景。
public class Client {
public static void main(String[] args) {
//创建AmericaLadder
ILadder americaLadder=new AmericaLadder();
//创建代理并将AmericaLadder作为构造函数传
ILadder myFriend=new MyFriendProxy(americaLadder);
//看风景了
myFriend.climbWall();
}
}
从编码的角度来说,代理模式分为静态代理和动态代理,上面的例子是静态代理,在代码运行前就已经存在了代理类的class编译文件,而动态代理则是在代码运行时通过反射来动态的生成代理类的对象,并确定到底来代理谁。也就是我们在编码阶段不需要知道代理谁,代理谁我们将会在代码运行时决定。
因为一个静态代理类只能服务一种类型的目标对象,在目标对象较多的情况下,会出现代理类较多、代码量较大的问题。想象一下如果想在其他国家的风景,还得创建其他国家的梯子,世界上有197个国家(特朗普说有184……),这是多么浩大的工程……
Java提供了动态的代理接口InvocationHandler,实现该接口需要重写invoke()方法。
因此看风景动态代理类如下:
public class DynamicAmercaLadder implements InvocationHandler {
private Object obj;
public DynamicAmercaLadder(Object obj){
this.obj=obj;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result=method.invoke(obj, args);
return result;
}
}
客户端实现如下:
public class Client {
private static void climbWall(ILadder iLadder){
//创建代理并将AmericaLadder作为构造函数传
DynamicAmercaLadder dynamicAmercaLadder = new DynamicAmercaLadder(iLadder);
//创建AmericaLadder的ClassLoader
ClassLoader loader = iLadder.getClass().getClassLoader();
//动态创建代理类
ILadder myFriend= (ILadder) Proxy.newProxyInstance(loader,new Class[]{ILadder.class},dynamicAmercaLadder);
//看风景了
myFriend.climbWall();
}
public static void main(String[] args) {
//创建AmericaLadder
ILadder americaLadder = new AmericaLadder();
climbWall(americaLadder);
//创建EnglandLadder
ILadder englandLadder = new EnglandLadder();
climbWall(englandLadder);
}
}
其中EnglandLadder:
public class EnglandLadder implements ILadder {
@Override
public void climbWall() {
System.out.println("我看到了大本钟");
}
}
从上面可以看出如果用静态代理,看美国的自由女神跟英国的大本钟我必须要分别创建对应的代理类,但是用动态代理,无论是看哪的风景只需要一个DynamicAmercaLadder就可以了。