代理設(shè)計(jì)模式 - 實(shí)現(xiàn) Retrofit 的 create

相信大家都很熟悉 Retrofit 了,這篇文章不會(huì)講使用,如果不是特別熟悉 Retrofit 的使用,可以去看看其他的一些文章。如果實(shí)在不想看那也沒關(guān)系,因?yàn)榻裉斓闹饕獌?nèi)容并不是 Retrofit ,而是代理設(shè)計(jì)模式。只是在講解的過程中順便講一下代理設(shè)計(jì)模式的運(yùn)用。先來看看開發(fā)中哪些地方可以用到:

  • Android 插件化架構(gòu)之繞過 AndroidManifest 檢測(cè)(動(dòng)態(tài)代理)
  • Android 數(shù)據(jù)庫(kù)實(shí)現(xiàn)數(shù)據(jù)的懶加載(靜態(tài)代理)
  • Android MVP 架構(gòu)設(shè)計(jì)(靜態(tài)代理和動(dòng)態(tài)代理)
  • Android Xutils 實(shí)現(xiàn) View 事件注入(動(dòng)態(tài)代理)
  • Android Retrofit 的 create 創(chuàng)建接口對(duì)象 (動(dòng)態(tài)代理)
  • Android Framework 層的 AMS
  • Android Framework 層的 Binder 驅(qū)動(dòng)

1.代理設(shè)計(jì)模式介紹


1.1 模式定義

為其他對(duì)象提供一種代理,以控制對(duì)這個(gè)對(duì)象的訪問,分為靜態(tài)代理和動(dòng)態(tài)代理。說到代理我們其實(shí)都明白,日常的生活中也并不少見,比如每天吃飯趕進(jìn)度,我們需要叫人給我們帶飯;我們?nèi)ャy行辦張卡,有銀行的業(yè)務(wù)員幫我們辦卡等等,編程的思想其實(shí)有的時(shí)候和生活差不多。

1.2 代理模式的簡(jiǎn)單事例

設(shè)計(jì)模式是一種思想,經(jīng)常在講定義的時(shí)候的確又很枯燥,但是無論哪一門語言我們又必須都得學(xué),如 iOS,Android,Unity3D 都離不開這些。既然是個(gè)簡(jiǎn)單的事例,我們就以這個(gè)銀行辦卡來說吧:

/**
 * description: 靜態(tài)代理設(shè)計(jì)模式 - 目標(biāo)接口
 * author: Darren on 2017/10/11 12:50
 * email: 240336124@qq.com
 * version: 1.0
 */
public interface IBank {
    void applyBank();
}
/**
 * description: 靜態(tài)代理設(shè)計(jì)模式 - 被代理對(duì)象
 * author: Darren on 2017/10/11 12:51
 * email: 240336124@qq.com
 * version: 1.0
 */
public class Man implements IBank{
    @Override
    public void applyBank() {
        System.out.println("辦卡");
    }
}
/**
 * description: 靜態(tài)代理設(shè)計(jì)模式 - 代理對(duì)象
 * author: Darren on 2017/10/11 12:52
 * email: 240336124@qq.com
 * version: 1.0
 */
public class BankSalesman implements IBank{
    private IBank bank;

    public BankSalesman(IBank bank){
        this.bank = bank;
    }

    @Override
    public void applyBank() {
        System.out.println("數(shù)據(jù)統(tǒng)計(jì)");
        bank.applyBank();
        System.out.println("完畢");
    }
}
/**
 * description:代理設(shè)計(jì)模式 - 測(cè)試
 * author: Darren on 2017/10/11 12:54
 * email: 240336124@qq.com
 * version: 1.0
 */
public class Client {
    public static void main(String[] args){
        Man man = new Man();
        BankSalesman salesman = new BankSalesman(man);
        salesman.applyBank();
    }
}

這就是我們的靜態(tài)代理設(shè)計(jì)模式,運(yùn)行結(jié)果很簡(jiǎn)單這里就不給出了,其實(shí)代理設(shè)計(jì)模式也很簡(jiǎn)單,其主要還是一種委托機(jī)制,真實(shí)對(duì)象將方法委托給代理對(duì)象,所以這里設(shè)計(jì)模式又有另一種說法,又叫委托模式,相信我們都不難理解。但是這里我們又要拋出一個(gè)問題,比如我現(xiàn)在要新增一個(gè)掛失我又得怎么寫呢?這里我就不寫了,接下來我們看下動(dòng)態(tài)代理模式。

1.3 動(dòng)態(tài)代理

與靜態(tài)代理不同的是,動(dòng)態(tài)代理通過反射在運(yùn)行時(shí)生成代理對(duì)象,Java也已經(jīng)給我們提供了一個(gè)便捷的動(dòng)態(tài)代理接口 InvocationHandler,源碼最終調(diào)用的是 Native 方法去生成我們的代理對(duì)象,其實(shí)在內(nèi)涵段子項(xiàng)目中,已經(jīng)帶大家看過動(dòng)態(tài)代理的源碼了。這里就不做太多介紹,看下上面的事例采用動(dòng)態(tài)代理,又有怎樣的改變:

/**
 * description: 動(dòng)態(tài)代理設(shè)計(jì)模式 - InvocationHandler
 * author: Darren on 2017/10/11 13:59
 * email: 240336124@qq.com
 * version: 1.0
 */
public class DynamicBankProxy implements InvocationHandler{
    private Object object;

    public DynamicBankProxy(Object object){
        this.object = object;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("數(shù)據(jù)統(tǒng)計(jì)");
        Object result = method.invoke(object,args);
        System.out.println("完畢");
        return result;
    }
}
/**
 * description:代理設(shè)計(jì)模式 - 測(cè)試
 * author: Darren on 2017/10/11 12:54
 * email: 240336124@qq.com
 * version: 1.0
 */
public class Client {
    public static void main(String[] args) {
        Man man = new Man();
        IBank bank = (IBank) Proxy.newProxyInstance(IBank.class.getClassLoader(),
                new Class<?>[]{IBank.class}, new DynamicBankProxy(man));
        bank.applyBank();
    }
}

2.實(shí)現(xiàn) Retrofit 的 create

對(duì)于 Retrofit 這里不會(huì)講得太詳細(xì),只會(huì)單獨(dú)講 create,后面會(huì)有 3-4 次的視頻直播,具體的大綱可以看下 Android進(jìn)階之旅 - 系統(tǒng)架構(gòu)篇。這里不也不結(jié)合 RXjava ,我們來看下 Retrofit 最普通的寫法:

public class RetrofitSimple {
    private static DataServiceInterface serviceInterface;

    static {
        Retrofit.Builder retrofitBuilder = new Retrofit.Builder().baseUrl("https://api.xxxxx.com/")
                .addConverterFactory(GsonConverterFactory.create());
        serviceInterface = retrofitBuilder.build().create(DataServiceInterface.class);
    }

    public static DataServiceInterface getService(){
        return serviceInterface;
    }
}
Call<Result> call = RetrofitSimple.getService().testMethod();

call.enqueue(new Callback<Result>() {
    @Override
    public void onResponse(Call<Result> call, Response<Result> response) {
        Result result = response.body();
        Log.e("TAG","result = "+result.code);
    }

    @Override
    public void onFailure(Call<Result> call, Throwable t) {
         
    }
});

這是沒有做任何封裝的,相信用過的都能看懂,如果都沒用過 Retrofit ,希望我們還是能多花寫時(shí)間去了解一下,因?yàn)榈胶竺嫖覀円约喝?shí)現(xiàn) Retrofit 的功能,也包括去修改它的源碼等等。上面代碼最主要的核心在于 Retrofit.create() 我們傳遞過去的是一個(gè)接口的 class 給我們返回的是一個(gè)對(duì)象,而這個(gè)對(duì)象其實(shí)就我們的代理對(duì)象,接下來我們簡(jiǎn)單的實(shí)現(xiàn)一下,我們把部分代碼先寫一下思路,后面我會(huì)帶著大家一個(gè)一個(gè)去補(bǔ)上的。

public class DarrenRetrofit {
    public <T> T create(Class<T> service) {
        return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[]{service}, new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                // 1. 先做一下打印,獲取方法名和參數(shù)
                /*Log.e("Method", method.getName());
                for (Object arg : args) {
                    Log.e("ARGS", arg+"");
                }*/

                // 2.解析方法注解參數(shù)到底是什么提交(Post) - 注解的不太懂請(qǐng)看前面的文章
                Annotation[] methodAnnotations = method.getAnnotations();
                for (Annotation methodAnnotation : methodAnnotations) {
                    // Post Get Multipart FormUrlEncoded 等等
                }

                // 3.解析 args 參數(shù)的注解

                // 4.封裝成 Call 或者其他對(duì)象返回

                return null;
            }
        });
    }
}
DarrenRetrofit retrofit = new DarrenRetrofit();
DataServiceInterface service = retrofit.create(DataServiceInterface.class);
Call<Result> call = service.testMethod();
call.enqueue(new Callback<Result>() {
    @Override
    public void onResponse(Call<Result> call, Response<Result> response) {
        Result result = response.body();
        Log.e("TAG","result = "+result.code);
    }

    @Override
    public void onFailure(Call<Result> call, Throwable t) {
        t.printStackTrace();
    }
});

所有分享大綱:Android進(jìn)階之旅 - 系統(tǒng)架構(gòu)篇

視頻講解地址:http://pan.baidu.com/s/1gfep8oN

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,062評(píng)論 25 709
  • Retrofit是squareup公司的開源力作,和同屬squareup公司開源的OkHttp,一個(gè)負(fù)責(zé)網(wǎng)絡(luò)調(diào)度,...
    藍(lán)灰_q閱讀 42,123評(píng)論 23 281
  • 念戀不舍 念起最初的相遇 不過長(zhǎng)廊一角,幽夢(mèng)一場(chǎng) 戀上少年的青澀 也不過目光相接,猛然心動(dòng) 遇見的剛剛好 卻是命運(yùn)...
    淚都掉了閱讀 402評(píng)論 0 0
  • 這幾天傍晚到附近的學(xué)校跑步時(shí),發(fā)現(xiàn)學(xué)生越來越多起來,開學(xué)了。 ——“開學(xué)了,你給孩子喝對(duì)奶了嗎?” ——“不,開學(xué)...
    Bevon英語翻譯閱讀 727評(píng)論 9 7
  • 春,漸入佳境,吾自京輾轉(zhuǎn)而返鄉(xiāng)。時(shí)值清明時(shí)節(jié),外春雨寒,歲寒而煥萬物而復(fù)蘇,參天巨木雖朽而護(hù)百兒孫,感明祖母之恩,...
    丁丁小午閱讀 364評(píng)論 2 1

友情鏈接更多精彩內(nèi)容