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();
}
}
}
上一篇: (三) 标准注解