ButterKnife源码之--为什么我写的ButterKnife中OnClick注解有问题

事情的经过是这样的:
我们知道ButterKnife的初始化时这样的ButterKnife.bind(this);,那我也希望自己封装的框架也是这个样子的,所以我打算这样Bind_MusicCutActivity.bindView(this);看上去没什么不一样,并且对findViewById的支持也没什么问题,问题出在哪了呢?出在我上一篇写OnClick的时候。

//我对findOnGrantedListenerForClass2( )方法加上点击注解,然后APT代码是这样的:
targetActivity.findViewById(2131165325).setOnClickListener( new OnClickListener() {
      @Override
      public void onClick(View v) {
        targetActivity.findOnGrantedListenerForClass2();
        android.util.Log.e("onclick","findOnGrantedListenerForClass2     is Clicked");
      }
    });

貌似没什么问题,其实targetActivity.findOnGrantedListenerForClass2();这个是报错的,原因很简单,因为bindView方法是静态的,那么只能访问静态类,这就扯淡了,我不可能把所有的点击方法和牵扯到的变量都弄成静态的。
看一下ButterKnife怎么搞的:

private static Unbinder createBinding(@NonNull Object target, @NonNull View source) {
    Class targetClass = target.getClass();
    if (debug) Log.d(TAG, "Looking up binding for " + targetClass.getName());
    Constructor constructor = findBindingConstructorForClass(targetClass);
    ..................................
    try {
      return constructor.newInstance(target, source);

再看下它生成的APT代码:

  @UiThread
  public MainActivity_ViewBinding(MainActivity target) {
    this(target, target.getWindow().getDecorView());
  }

  @UiThread
  public MainActivity_ViewBinding(MainActivity target, View source) {
    this.target = target;

    target.recyclerView = Utils.findRequiredViewAsType(source, R.id.activity_RecyclerView, "field 'recyclerView'", RecyclerView.class);
  }

一目了然,它是通过反射获取到类,然后constructor.newInstance(target, source)走构造函数这,所以它的相关代码都是在构造函数MainActivity_ViewBinding(MainActivity target, View source)初始化的时候执行的。很鸡贼的做法,但是我不想这么做,我只想封装个轻量级的ButterKnife来满足我的懒惰,其他的不想搞的这么复杂,不然岂不是和我懒的初衷相悖了啊。

具体做法

你可以用发射,那我也可以啊。我用另外一个类包裹一下好了。

public class Bind {
    private static final String TAG = "Bind";
    public static void bindView(Activity activity){
        try {
        Class listenerClass = Class.forName("com.zhujie.zhujie.Bind_"+activity.getClass().getSimpleName());
        Object o = listenerClass.newInstance();
        Method method = listenerClass.getDeclaredMethod("bindView",activity.getClass());
        method.invoke(o,activity);
    } catch (ClassNotFoundException e) {
        Log.e(TAG, "ClassNotFoundException: " + e.toString());
        e.printStackTrace();
    } catch (NoSuchMethodException e) {
        Log.e(TAG, "NoSuchMethodException: " + e.toString());
        e.printStackTrace();
    } catch (InvocationTargetException e) {
        Log.e(TAG, "InvocationTargetException: " + e.toString());
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    } catch (InstantiationException e) {
        e.printStackTrace();
    }
    }
}

你可能感兴趣的:(Android,注解)