Retrofit基本使用
參考官方文檔:https://square.github.io/retrofit/
馬老師教導我們要穿一手鞋,而且官方文檔足夠的詳細。
代理模式
在我們使用 Retrofit 進行網絡請求時,實際其內部使用 OkHttp 來完成網絡請求的,然後,使用我們傳入的 “類型轉換器” 把響應轉換成我們指定的類型。定義了一個接口並調用了該接口的方法,然後就拿到了請求的結果,這看上去非常簡潔,而這其中的最功不可沒的就是動態代理。
代理模式也叫委託模式,是結構型設計模式的一種。在Android中代理模式有很多,如Binder。生活中也有很多代理的例子,例如代購、看國外的風景等。
代理模式結構圖:
- Client:客戶端類。
- Subject:抽象主題類,用於聲明真實主題與代理的共同接口方法。
- RealSubject:真實主題類,定義了代理所表示的真實對象,客戶端通過代理類間接的調用真實主題類的方法。
- ProxySubject:代理類,抽象主題類的實現類。並持有對真實主題類的引用,在其所實現的接口方法中調用真實主題類中相應的接口方法執行。
代理模式的簡單實現
假設我想看看qiang外的風景,但是門被焊死了,焊門的兄弟臨走連窗戶也給堵上了,這個時候我就需要一個梯子(因爲我不夠高)
抽象主題類(Subject)
抽象主題類具有真實主題類和代理的共同接口方法,我想看風景,那麼共同的方法就是看風景:
public interface ILadder {
/**
* 看風景
*/
void climbWall();
}
真實主題類(RealSubject)
爲了能看到腐國的自由女神像,所以搞一個腐國的梯子(AmericaLadder),它還得有看風景的能力:
public class AmericaLadder implements ILadder {
@Override
public void climbWall() {
System.out.print("我看到了自由女神像");
}
}
代理類(ProxySubject)
梯子並不是我的,是我的一個朋友提供給我的,所以我是通過我的朋友得到的這個梯子實現的看風景的能力:
public class MyFriendProxy implements ILadder {
/**
* 朋友的梯子
*/
private ILadder iLadder;
public MyFriendProxy(ILadder iLadder){
this.iLadder=iLadder;
}
@Override
public void climbWall() {
iLadder.climbWall();
}
}
客戶端類(Client)
有了梯子,才能看到外面的風景。
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就可以了。