欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2022-07-08 10:25:28
...

事情的经过是这样的:
我们知道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<? extends Unbinder> 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();
    }
    }
}
相关标签: 注解