findViewById注解
实现效果:
只要在需要注解的Activity中声明开启,就能够对字段绑定注解:像这样:
@BindView(R.id.recycler)
private RecyclerView recyclerView;
@BindView(R.id.rg)
private RadioGroup radioGroup;
@BindView(R.id.tv)
private RadioGroup textView;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(getLayoutId());
MyTool.init(this);
}
开始实现:
1、定义一个注解接口,然后在它上面声明该注解用于字段,并且在程序编译时保留该注解:
@Target({ElementType.FIELD}) //声明该注解用于字段
@Retention(RetentionPolicy.RUNTIME) //跑起来时用
public @interface BindView{
int value(); //注解传入的参数为int类型
}
说明一下:
@Retention:注解的保留位置
@Retention(RetentionPolicy.SOURCE) //注解仅存在于源码中,在class字节码文件中不包含
@Retention(RetentionPolicy.CLASS) // 默认的保留策略,注解会在class字节码文件中存在,但运行时无法获得
@Retention(RetentionPolicy.RUNTIME) // 注解会在class字节码文件中存在,在运行时可以通过反射获取到
@Target:注解的作用目标
@Target(ElementType.TYPE) //接口、类、枚举
@Target(ElementType.FIELD) //字段、枚举的常量
@Target(ElementType.METHOD) //方法
@Target(ElementType.PARAMETER) //方法参数
@Target(ElementType.CONSTRUCTOR) //构造函数
@Target(ElementType.LOCAL_VARIABLE)//局部变量
扫描二维码关注公众号,回复: 8498800 查看本文章@Target(ElementType.ANNOTATION_TYPE)//注解
@Target(ElementType.PACKAGE) ///包
2、对注解做反射完成想要的效果:
public class MyTool {
public MyTool() {
}
public static void init(Activity activity) {
try {
bindView(activity); //调用下面这个方法
} catch (IllegalAccessException var2) {
var2.printStackTrace();
} catch (IllegalArgumentException var3) {
var3.printStackTrace();
}
}
private static void bindView(Activity activity) throws IllegalAccessException, IllegalArgumentException {
Class clazz = activity.getClass(); //获取当前Activity的类对象
Field[] declaredFields = clazz.getDeclaredFields(); //获取这个类对象里面所有的字段(数组集合)
for(int i = 0; i < declaredFields.length; ++i) { //遍历这个数组
Field field = declaredFields[i]; //拿到单个字段
BindView bind = (BindView)field.getAnnotation(BindView.class); //拿到字段上面的BindView注解
if (bind != null) { //如果有BindView注解的话
int value = bind.value(); //获取注解里面的int值,也就是我们要的id
View findViewById = activity.findViewById(value); //找到这个View
field.setAccessible(true); //取消Java的权限控制检查
field.set(activity, findViewById); //把该字段和view联系起来
}
}
}
}
说的很清楚了,至此,我们的findViewById的注解BindView就可以用了
接下来是对onClick点击事件的绑定做注解
实现效果:
@ClickView(R.id.btn)
public void click(View v){
//do something
}
实现原理和字段绑定差不多:
开始实现:
1、声明注解接口,并且指明是对方法做注解,传入的参数也是int类型:
@Target({ElementType.METHOD}) //对方法做注解
@Retention(RetentionPolicy.RUNTIME)
public @interface ClickView {
int value();
}
2、获取有该注解的方法进行绑定OnClick事件(和刚刚的MyTool写在一起吧,整一个MyTool类如下):
public class MyTool{
public MyTool() {
}
public static void init(Activity activity) {
try {
bindView(activity);
bindClickEvent(activity);
} catch (IllegalAccessException var2) {
var2.printStackTrace();
} catch (IllegalArgumentException var3) {
var3.printStackTrace();
}
}
private static void bindView(Activity activity) throws IllegalAccessException, IllegalArgumentException {
Class clazz = activity.getClass();
Field[] declaredFields = clazz.getDeclaredFields();
for(int i = 0; i < declaredFields.length; ++i) {
Field field = declaredFields[i];
BindView bind = (BindView)field.getAnnotation(BindView.class);
if (bind != null) {
int value = bind.value();
View findViewById = activity.findViewById(value);
field.setAccessible(true);
field.set(activity, findViewById);
}
}
}
private static void bindClickEvent(final Activity activity) {
Class clazz = activity.getClass();
Method[] declaredMethods = clazz.getDeclaredMethods(); //获取到这个类的所有方法
for(int i = 0; i < declaredMethods.length; ++i) { //遍历
final Method method = declaredMethods[i];
ClickView clickView = (ClickView)method.getAnnotation(ClickView.class); //获取方法上面为ClickView的注解
if (clickView != null) {
int value = clickView.value(); //拿参数:获取到view的id
final View findViewById = activity.findViewById(value); //找到这个view
findViewById.setOnClickListener(new OnClickListener() { //给view设置点击事件
public void onClick(View arg0) {
method.setAccessible(true); //别忘记了这个,才能拿到method下面的私有属性
method.invoke(activity, findViewById); //该方法和这个view建立点击事件的联系
}
});
}
}
}
}