Retrofit2.X解析(一)Retrofit基本使用以及動態代理

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就可以了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章