通常情况下,我们在写控件的时候都会调用findViewById的方法来获取View实例,并且还要强制转换(Android studio 3.0之后不需要),非常繁琐,当然了市面上也有ButterKinfe这样的的第三方库来辅助开发者提高开发效率,如果我们自己去实现这样的框架其实也很简单,几个步骤就可以完成,不过首先要对注解有比较深刻的理解。
第一步:定义注解
代码如下:
@Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface LcsBindView { int value(); }
主要来说定义注解分三步,@inteface标明当前是注解类,@号不能漏掉,否则变成了接口了
@Target注解
我们注解作用的目标,这里是ElementType.FIELD,也就是作用于字段的,还有其他的修饰如下:
1.CONSTRUCTOR:用于描述构造器
2.FIELD:用于描述字段
3.LOCAL_VARIABLE:用于描述局部变量
4.METHOD:用于描述方法
5.PACKAGE:用于描述包
6.PARAMETER:用于描述参数
7.TYPE:用于描述类、接口(包括注解类型) 或enum声明
@Retention注解
注解的运行级别
RetentionPolicy的类型有以下几种
1.SOURCE:在源文件中有效(即源文件保留)
2.CLASS:在class文件中有效(即class保留)
3.RUNTIME:在运行时有效(即运行时保留)
看解释应该明白,他们的级别是:1<=2<=3
至此注解就定义完成了。
第二步骤:绑定关联
顾名思义,简单的定义是使用不了的,我们要把控件和注解关联起来,才能正常使用
线上代码:
//核心方法 public static void bindViews(Activity activity) { Class<? extends Activity> activityClass = activity.getClass();//获取activity的class Field[] fields = activityClass.getDeclaredFields();//获取activity的字段 //遍历所有的字段 for (Field field : fields) { //获取该字段的注解 LcsBindView lcsBindView = field.getAnnotation(LcsBindView.class); //!=null 说明该字段有注解并且是指定的注解 if (lcsBindView != null) { //获取到注解总传入的数值value int viewId = lcsBindView.value(); if(viewId != -1){ try { //获取到activity中findViewById的方法 Method findViewByIdMethod = activityClass.getMethod("findViewById", int.class); try { //执行findViewById方法 Object resView = findViewByIdMethod.invoke(activity, viewId); //允许通过反射访问私有变量 field.setAccessible(true); //把字段的值设置该view的实例 field.set(activity, resView); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } } catch (NoSuchMethodException e) { e.printStackTrace(); } } } } }
先看里面的注释,大概可以理解我们的关联步骤,主要是先获取到activity的class实例,之后在获取到类中的所有字段,之后再进行遍历、获取字段的注解类,如果是当前我们需要的注解类,我们再获取到activity中的findViewById的方法,通过反射去执行这个方法,并且把获取到value也就是控件Id传进去,那么我们的控件就被实例化了,然后再把返回的object的对象设置到该对应字段上面,这样在activity中用此字段就不会发生空指针了,整个过程就结束了,activity中的使用如下:
@LcsBindView(R.id.tv_test) private TextView tvTest;
BindViewUtils.bindViews(this); tvTest.setText("我是通过 @LcsBindView 找到的,哈哈哈~");
先进行注解修饰,再进行注解关联,就可以使用了,是不是很简单呢:D