还在使用findViewById()?教你如何注解式绑定控件

在android开发中,进行界面渲染的时候,必须先对各种View进行初始化,比如:

<span style="font-size:18px;">TextView t = (TextView) findViewById(R.id.x);</span>

这是我们最常见的获取xml布局中一个textview对象的过程。如果视图过多的话,就会重复的调用这个方法。这样的话,不仅对开发者来说很烦躁,而且从视觉上看代码显得很臃肿。

有一种解决方法是使用注解的方式来初始化这些视图控件,但是这种方法会牺牲一定的性能,因为它是通过反射的方式实现的,不过在可以接受的范围内。下面就来说说是如何实现的。


首先编写一个注解类,如下:

<span style="font-size:18px;">@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface BindView {
    public int id();
}</span>

@Target(ElementType.FIELD):表示我们需要注解的是一个字段
@Retention(RetentionPolicy.RUNTIME):表示在源码、编译好的.iclass文件中保留信息,在执行的时候会把这些信息加载到JVM中。


然后编写一个处理注解的方法,

我们的目标是根据View的ID取初始化View,所以首先得取到view的ID,很简单,通过注解类的id()方法便可以得到。

但是BindView是不能new的,这时就需要用到Java的反射机制。

我们知道,每一个继承自Object类的类都会继承一个getClass()方法,这个方法返回的是该类的Class对象,同时也是该类的二进制对象。

Class中有一个方法叫getDeclaredFields(),是用来返回这个类的全部字段,返回类型是Field[]

通过Field对象的getAnnotation(Class<?>)方法,我们可以获取到任何一个注解类型的对象,比如BindView

代码如下:

public static void initBindView(Object currentClass, View sourceView) {
		// 通过反射获取到全部属性,反射的字段可能是一个类(静态)字段或实例字段
		Field[] fields = currentClass.getClass().getDeclaredFields();
		if (fields != null && fields.length > 0) {
			for (Field field : fields) {
				// 返回BindView类型的注解内容
				if (field.isAnnotationPresent(BindView.class)) {
					BindView bindView = field.getAnnotation(BindView.class);
					int viewId = bindView.id();;
					try {
						field.setAccessible(true);
						// 将currentClass的field赋值为sourceView.findViewById(viewId)
						field.set(currentClass, sourceView.findViewById(viewId));
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
			}
		}
	}

注意,该方法必须在setContentView之后调用。


最后在你的activity或fragment里通过如下的方式

@BindView(id = R.id.x)
private TextView t;

就可以初始化TextView了,而不用再去编写 TextView t = (TextView) findViewById(R.id.x); 这一部分的代码了。


 

 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值