看ButterKnife源码
public @interface OnClick {
/** View IDs to which the method will be bound. */
@IdRes int[] value() default { View.NO_ID };
}
在实际的使用中呢,也很方便,直接在方法上加上注解就可以,但是我们发现它的注解方法只支持不带参的方法,或者参数是View类型的方法。假如我们注解修饰的方法是别的类型的呢?比如:
@OnClick(R.id.textView2 )
public void textView2Click(String msg){
}
那么看一下APT生成的
view.setOnClickListener(new DebouncingOnClickListener() {
@Override
public void doClick(View p0) {
target.textView2Click();//这一行是爆红的,错误的。
}
});
这样我们可以直观的知道,它是不支持带参的OnClick的:
- 它的注解没有给你留设置参数的位置
- 它的注解编译器也没有给这个参数设置默认值
这个时候有两个疑问:
- ButterKnife不支持,那么我可不可以自定义?
- 为什么ButterKnife不支持呢?
其实这个问题归根到底是一个问题 – 注解支持传递什么样的参数?
我们来站在实际开发中假设一下,如果我们要自定义注解支持传参,那么在注解上要能传参,这样编译器才能把参数加上,如果我们要传递String类型的参数,貌似还是很简单的,我们只需要把String.class和你的参数传过去就行了。但是如果你是两个甚至多个String类型的参数呢?是不是要告诉编译器多个参数的类型和多个参数的值!
这时你就感觉这样好麻烦,我写个数组放进去好了:
public @interface OnClick {
/** View IDs to which the method will be bound. */
int[] id() default { 0 };
Class[] key();
String[] value();
}
但是我们再往后想,我们不可能只用基本类型,如果用到别的类型呢?比如说:我感觉数组的形式好麻烦,我想用类似OKHTTP的那样,用param来包裹key和value呢?这个时候你希望是这样的:
public @interface OnClick {
int[] id() default { 0 };
Params[] params(); //报错:invalid type for annotions member
}
注解不支持自定义类型。这就很限制我们的发挥了,因为很多时候我们可能是传个数组,传个列表,或者传个Object。下面引出重点:
注解支持的类型
下面部分转自:http://www.voidcn.com/article/p-xoutqlxc-bhy.html
- A primitive type : 基本类型(java的八种基本类型:byte、short、int、long、float、double、char、boolean)
- String : 字符串
- Class :Class
- An enum type : 枚举
- An annotation type :注解
- An array type :类型为以上任一类型的数组
官方文档:https://docs.oracle.com/javase/specs/jls/se8/html/jls-9.html#jls-9.6.1