三、解決方案

2018-02-24 15:48 更新

三、解決方案

3.1 一行代碼寫反射

作為一個(gè)Android程序員,索性就拿TextView這個(gè)類開刀吧。首先定義一個(gè)類變量:

TextView mTv;

通過反射得到實(shí)例:

// 有參數(shù),建立類
mTv = Reflect.on(TextView.class).create(this).get();

// 通過類全名得到類
String word = Reflect.on("java.lang.String").create("Reflect TextView").get();

// 無參數(shù),建立類
Fragment fragment = Reflect.on(Fragment.class).create().get();

通過反射調(diào)用方法:

// 調(diào)用無參數(shù)方法
L.d("call getText() : " + Reflect.on(mTv).call("getText").toString());

// 調(diào)用有參數(shù)方法
Reflect.on(mTv).call("setTextColor", 0xffff0000);

通過反射get、set類變量
TextView中有個(gè)mText變量,來看看我們怎么接近它。

// 設(shè)置參數(shù)
Reflect.on(mTv).set("mText", "---------- new Reflect TextView ----------");

// 獲得參數(shù)
L.d("setgetParam is " + Reflect.on(mTv).get("mText"));

3.2 什么時(shí)候該用反射,什么時(shí)候不用反射

又到了這樣權(quán)衡利弊的時(shí)候了,首先我們明確,在日常開發(fā)中盡量不要用反射,除非遇到了必須要通過反射才能調(diào)用的方法。比如我在做一個(gè)下拉通知中心功能的時(shí)候就遇到了這樣的情況。系統(tǒng)沒有提供api,所以我們只能通過反射進(jìn)行調(diào)用,所以我自己寫了這樣一段代碼:

<uses-permission android:name="android.permission.EXPAND_STATUS_BAR"/>
private static void doInStatusBar(Context mContext, String methodName) {
    try {
        Object service = mContext.getSystemService("statusbar");
        Method expand = service.getClass().getMethod(methodName);
        expand.invoke(service);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

/**
 * 顯示消息中心
 */
public static void openStatusBar(Context mContext) {
    // 判斷系統(tǒng)版本號
    String methodName = (VERSION.SDK_INT <= 16) ? "expand" : "expandNotificationsPanel";
    doInStatusBar(mContext, methodName);
}

/**
 * 關(guān)閉消息中心
 */
public static void closeStatusBar(Context mContext) {
    // 判斷系統(tǒng)版本號
    String methodName = (VERSION.SDK_INT <= 16) ? "collapse" : "collapsePanels";
    doInStatusBar(mContext, methodName);
}

先來看看利用jOOR寫的doInStatusBar方法會簡潔到什么程度:

private static void doInStatusBar(Context mContext, String methodName) {
    Object service = mContext.getSystemService("statusbar");
    Reflect.on(service).call(methodName);
}

哇,就一行代碼啊,很爽吧~
爽完了,我們就來看看反射問題吧。因?yàn)椴皇窍到y(tǒng)給出的api,所以谷歌在不同的版本上用了不同的方法名來做處理,用反射的話我們就必須進(jìn)行版本的判斷,這是需要注意的,此外反射在性能方面確實(shí)不好,這里需要謹(jǐn)慎。
我的建議:
如果一個(gè)類中有很多地方都是private的,而你的需求都需要依賴這些方法或者變量,那么比起用反射,推薦把這個(gè)類復(fù)制出來,變成自己的類,像是toolbar這樣的類就可以進(jìn)行這樣的操作。
在自己寫框架的時(shí)候,我們肯定會用到反射,很簡單的例子就是事件總線和注解框架,翔哥就說過一句話:無反射,無框架。也正因?yàn)槭亲约簩懙目蚣?,所以通過反射調(diào)用的方法名和參數(shù)一般不會變,更何況做運(yùn)行時(shí)注解框架的話,反射肯定會出現(xiàn)。在這種情況下千萬不要害怕反射,索性放心大膽的做。因?yàn)樗鼤屇阃瓿珊芏嗖豢赡芡瓿傻娜蝿?wù)。

總結(jié)下來就是:
實(shí)際進(jìn)行日常開發(fā)的時(shí)候盡量少用反射,可以通過復(fù)制原始類的形式來避免反射。在寫框架時(shí),不避諱反射,在關(guān)鍵時(shí)利用反射來助自己一臂之力。

以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號