codecamp

三、解决方案

三、解决方案

3.1 一行代码写反射

作为一个Android程序员,索性就拿TextView这个类开刀吧。首先定义一个类变量:

TextView mTv;

通过反射得到实例:

// 有参数,建立类
mTv = Reflect.on(TextView.class).create(this).get();

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

// 无参数,建立类
Fragment fragment = Reflect.on(Fragment.class).create().get();

通过反射调用方法:

// 调用无参数方法
L.d("call getText() : " + Reflect.on(mTv).call("getText").toString());

// 调用有参数方法
Reflect.on(mTv).call("setTextColor", 0xffff0000);

通过反射get、set类变量
TextView中有个mText变量,来看看我们怎么接近它。

// 设置参数
Reflect.on(mTv).set("mText", "---------- new Reflect TextView ----------");

// 获得参数
L.d("setgetParam is " + Reflect.on(mTv).get("mText"));

3.2 什么时候该用反射,什么时候不用反射

又到了这样权衡利弊的时候了,首先我们明确,在日常开发中尽量不要用反射,除非遇到了必须要通过反射才能调用的方法。比如我在做一个下拉通知中心功能的时候就遇到了这样的情况。系统没有提供api,所以我们只能通过反射进行调用,所以我自己写了这样一段代码:

<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) {
    // 判断系统版本号
    String methodName = (VERSION.SDK_INT <= 16) ? "expand" : "expandNotificationsPanel";
    doInStatusBar(mContext, methodName);
}

/**
 * 关闭消息中心
 */
public static void closeStatusBar(Context mContext) {
    // 判断系统版本号
    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);
}

哇,就一行代码啊,很爽吧~
爽完了,我们就来看看反射问题吧。因为不是系统给出的api,所以谷歌在不同的版本上用了不同的方法名来做处理,用反射的话我们就必须进行版本的判断,这是需要注意的,此外反射在性能方面确实不好,这里需要谨慎。
我的建议:
如果一个类中有很多地方都是private的,而你的需求都需要依赖这些方法或者变量,那么比起用反射,推荐把这个类复制出来,变成自己的类,像是toolbar这样的类就可以进行这样的操作。
在自己写框架的时候,我们肯定会用到反射,很简单的例子就是事件总线和注解框架,翔哥就说过一句话:无反射,无框架。也正因为是自己写的框架,所以通过反射调用的方法名和参数一般不会变,更何况做运行时注解框架的话,反射肯定会出现。在这种情况下千万不要害怕反射,索性放心大胆的做。因为它会让你完成很多不可能完成的任务。

总结下来就是:
实际进行日常开发的时候尽量少用反射,可以通过复制原始类的形式来避免反射。在写框架时,不避讳反射,在关键时利用反射来助自己一臂之力。

二、分析
四、后记
温馨提示
下载编程狮App,免费阅读超1000+编程语言教程
取消
确定
目录

关闭

MIP.setData({ 'pageTheme' : getCookie('pageTheme') || {'day':true, 'night':false}, 'pageFontSize' : getCookie('pageFontSize') || 20 }); MIP.watch('pageTheme', function(newValue){ setCookie('pageTheme', JSON.stringify(newValue)) }); MIP.watch('pageFontSize', function(newValue){ setCookie('pageFontSize', newValue) }); function setCookie(name, value){ var days = 1; var exp = new Date(); exp.setTime(exp.getTime() + days*24*60*60*1000); document.cookie = name + '=' + value + ';expires=' + exp.toUTCString(); } function getCookie(name){ var reg = new RegExp('(^| )' + name + '=([^;]*)(;|$)'); return document.cookie.match(reg) ? JSON.parse(document.cookie.match(reg)[2]) : null; }