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这样的类可以进行这样的操作。
  在自己写框架的时候,我们肯定会用到反射,很简单的例子是事件总线和注解框架,翔哥说过一句话:无反射,无框架。也正因为是自己写的框架,所以通过反射调用的方法名和参数一般不会变,更何况做运行时注解框架的话,反射肯定会出现。在这种情况下千万不要害怕反射,索性放心大胆的做。因为它会让你完成很多不可能完成的任务。
  总结下来是:
  实际进行日常开发的时候尽量少用反射,可以通过复制原始类的形式来避免反射。在写框架时,不避讳反射,在关键时利用反射来助自己一臂之力。
  四、后记
  我们终于完成了用一行代码写反射,避免了很多无意义的模板式代码。需要再次说明的是,本文是依据jOOR 进行编写的,这里有原项目readme的中文翻译。
  jOOR是我无意中遇到的开源库,第一次见到它时我知道这个是我想要的,因为那时候我被反射搞的很乱,而它简洁的编码方式给我带来了新的思考,大大提高了代码可读性。顺便一说,作者人比较好(是死活不愿意让我放入中文的readme),技术也很不错。该项目有很详细的测试用例,并且还给出了几个类似的反射调用封装库。可见作者在写库时做了大量的调研和测试工作,让我们可以放心的运用该库(其实两个类)。
  本文希望带给大家一个反射的新思路,给出一个简单实用的反射写法,希望能被大家迅速运用到实践中去。更加重要的是,通过对jOOR的分析,让我知道了写库前应该调研类似的库,而不是完全的创造新轮子,调研和测试是代码稳定性的重要保障。