//Retention有三种策略
1.RetentionPolicy.CLASS 只在字节码起效果
2.RetentionPolicy.SOURCE 只在编译期间效果,起标识作用
3RetentionPolicyRUNTIME 运行时起作用,一般用于反射
//Target表示该注解的作用域
ElementType.FIELD 表示可以作用在成员属性上
ElementType.METHOD表示该注解可以作用在成员方法上
ElementType.TYPE表示该注解可以作用在类或接口上
当需要作用在多个作用域时可以通过@Target({ ElementType.FILD , ElementType.METHOD , ElementType.CLASS })
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface ContentView{
int value();//当只有一个属性时,只能起value这个名字,此时获取注解的值时也不需要用ContentView(value = 123),而是直接使用BindView(123),int表示value接收的数据类型。
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface BindView {
int value();
}
@ContentView(R.layout.activity_main) //该注解的作用是给该类设置一个布局文件,其功能和setContentView一样,下面介绍实现
public class MainActivity extends Activity{
@BindView(R.id.tv_title) //给title设置一个控件,其功能和findViewById功能一样,下面介绍
private TextView title;
@BindView(R.id.iv_icon)
private ImageView icon;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
ViewInject.inject(this);
title.setText("测试");
icon.setBackgroundResource(R.drawable.ic_head_bg);
}
}
public class ViewInject {
public static void inject(Activity activity) {
Class<? extends Activity> activityClass = activity.getClass();//通过对象获取Class
if (activityClass.isAnnotationPresent(ContentView.class)) { //判断该类上有没ContentView这个注解,有就返回true,否则返回false
ContentView annotation = activityClass.getAnnotation(ContentView.class);//获取ContentView这个注解
int value = annotation.value();//获取注解上的值
try {
//此处只能用getMethod而不能用getDeclaredMethod方法
//getMethod方法只能获取public类型的方法包括父类的,而getMethod能获取private、protected、public、default类型的方法,但是不能获取父类的方法
//而此处的setContentView方法是父类的,故只能使用getMethod
Method method = activityClass.getMethod("setContentView", int.class);//获取形参为int类型的setContentView这个方法,
method.setAccessible(true);//暴力访问,如果不设置将不能访问private修饰的成员
method.invoke(activity, value);//调用activity这个对象的method方法,该方法的参数为value
Log.i("TAG", "inject");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Field[] fields = activityClass.getDeclaredFields();//获取本类中所有字段,包括private、protected、default、public,但不包括父类的
for(Field field : fields){
if(field.isAnnotationPresent(BindView.class)){//判断该类上是否有BindView这个注解
BindView annotation = field.getAnnotation(BindView.class);//获取这个字段的BindView注解
int value = annotation.value();//获取这个注解的值
try {
Method method = activityClass.getMethod("findViewById", int.class);获取这个类中的findViewById方法
method.setAccessible(true); //由于findViewById是public类型的,故此处可以不调用该方法
int resultView = (int)method.invoke(activity, value);//方法调用后会有一个返回结果
field.setAccessible(true); //此处一定要使用,否则将不能访问field字段,因为很多时候我们都会把View设置为private访问权限
field.set(activity, resultView);
Log.i("TAG", "success4");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}