原理:获取到我们的注解,通过java反射调用为特定元素设置值
1、定义注解
@Target(ElementType.FIELD)//表示用在字段上
@Target(ElementType.TYPE)//表示用在类上
@Retention(RetentionPolicy.RUNTIME)// 表示是在声明周期运行的
RetentionPoicy的取值有:
1.SOURCE:在源文件中有效(即源文件保留)
2.CLASS:在class文件中有效(即class保留)
3.RUNTIME:在运行时有效(即运行时保留)
Retention注解有一个属性value,是RetentionPolicy类型的,Enum RetentionPolicy是一个枚举类型,
这个枚举决定了Retention注解应该如何去保持,也可理解为Rentention 搭配 RententionPolicy使用。
RetentionPolicy有3个值:CLASS RUNTIME SOURCE
用@Retention(RetentionPolicy.CLASS)修饰的注解,表示注解的信息被保留在class文件(字节码文件)中当程序编译时,但不会被虚拟机读取在运行的时候;用@Retention(RetentionPolicy.SOURCE )修饰的注解,表示注解的信息会被编译器抛弃,不会留在class文件中,注解的信息只会留在源文件中;
用@Retention(RetentionPolicy.RUNTIME )修饰的注解,表示注解的信息被保留在class文件(字节码文件)中当程序编译时,会被虚拟机保留在运行时,
所以他们可以用反射的方式读取。RetentionPolicy.RUNTIME 可以让你从JVM中读取Annotation注解的信息,以便在分析程序的时候使用.
public @interface ViewId { //注解名字:VIewID
int value() default 0; //注解的属性名字:value,值类型 :int *当属性名为value时间,使用时可省略属性名,其他的不可以
}
2、注解的解释方法
public class ViewIdControler {
private Activity context;
public void regist(Activity context) {//为当前的Activity注册
this.context = context;
function();
}
// 解释注解
private void function() {
try {
Class<?> clazz = context.getClass(); //获得运行时类对象
Field[] fields = clazz.getDeclaredFields(); //获得申明的属性S
for (Field f : fields) {
// 判断是否带有ViewID的注解
if (f.isAnnotationPresent(ViewId.class)) {
ViewId viewId = f.getAnnotation(ViewId.class);// 获取注解
int id = viewId.value(); //通过属性名字,获取值
if (id > 0) {
f.setAccessible(true); //这个我也不太清楚
f.set(context, context.findViewById(id)); //设置值
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
3、使用自定义的注解
public class MainActivity extends Activity implements ViewIterface,
OnClickListener {
@ViewId(R.id.mima)
private EditText passWorld;
@ViewId(R.id.name)
private EditText name;
@ViewId(R.id.login)
private Button login;
private ProgressDialog dialog;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ViewIdControler controler = new ViewIdControler();
controler.regist(this);
initViews();
}
//如此就不用findviewById了