View的自动注入 首先需要 相关的View以及 对应的资源ID
因此,在Activity中声明相关View
private TextView tv;
而自动注入,我们需要通过Activity对象获得该activity对象中的TextView对象。
此时 我们通过Activity对象需要获得内部声明的属性,需要先得到相关的类,再通过类获得相关的属性
//自动对View进行view与id绑定 需要对应的view与viewId
public static void injectView(Activity activity) {
//放射是基于Class的 这个时候我们得到的只是传入的activity对象,需要获得相关类
Class<? extends Activity> cls = activity.getClass();
}
获得类对象后,可以通过getDeclaredFields方法获得该类的属性数组
//获得此类所有的成员
Field[] declaredFields = cls.getDeclaredFields();
对该数组进行遍历,获取需要自动注入的View对象,此时,需要对其加入标识(既注解)获得相关View对象
因此 创建相关注解
因为是动态注入 因此其注解因保留至RUNTIME时
//运行时获取反射
@Retention(RetentionPolicy.RUNTIME)
而View的自动注入,不仅需要该View对象,还需要ViewId,才能进行自动注入,我们通过注解获取到这是需要进行注入的View
因此 需要通过注解进行传入ViewId值
//因为是对View的自动注入,该注解因该用在相关属性上
@Target(ElementType.FIELD)
public @interface InjectView {
//@IdRes做语法检查 传入ViewId作为值
@IdRes int value();
}
此时,我们将这个注解用在相关的属性上
@InjectView(R.id.tv)
private TextView tv;
现在,TextView被进行了相关的标注 继续对Activity对象中的所有Filed域进行遍历,并通过注解进行判定
for (Field filed : declaredFields) {
// 判断属性是否被InjectView注解声明 从而获取对应的Views
if (filed.isAnnotationPresent(InjectView.class)){
//获得该注解
InjectView injectView = filed.getAnnotation(InjectView.class);
//获得了注解中设置的id
int id = injectView.value();
//获取到了相关Id的View
View view = activity.findViewById(id);
//反射设置 属性的值
filed.setAccessible(true); //设置访问权限,允许操作private的属性
try {
//反射赋值 因为类里面有多个filed 不通过set无法将特定filed与该View绑定
filed.set(activity,view);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
使用
InjectUtils.injectView(this);
现在这种技术已经不用了,我们可以通过APT进行View的自动注入
------ 未完待续