注意:本篇文章是本人阅读相关文章所写下的总结,方便以后查阅,所有内容非原创,侵权删。
本篇文章内容来自于
Android高级进阶 顾浩鑫
Android中的自定义注解(反射实现-运行时注解)
目录
- 元注解
- 反射+运行时注解实现
1. 元注解
元注解,就是用来定义和实现注解的注解。
总共有五种。
1⃣️@Target 用来指定注解所适用的对象范围
如果一个注解的定义没有使用@Target修饰,那么它可以用在除了TYPE_USE和TYPE_PARAMEYER之外的其他类型中。
@Target参数取值
//注解参数取值是一个ElementType类型的数组。
元素类型 适用于
ANNOTATION_TYPE 注解类型声明
CONSTRUCTOR 构造函数
FIELD 实例变量
LOCAL_VARIABLE 局部变量
METHOD 方法
PACKAGE 包
PARAMETER 方法参数或者构造函数的参数
TYPE 类(包含enmu)和接口(包含注解类型)
TYPE_PARAMETER 类型参数
TYPE_USER 类型的用图
使用案例
@Target({ElementType.TYPE,ElementType.PACKAGE})
public @interface CrashReport
2⃣️@Retention:用来指明注解的访问范围
也就是在什么级别保留注解
未指定类型时,默认是CLASS类型。
参数取值
源码级注解:
在定义注解接口时,使用@Retention(RetentionPolicy.SOURCE)修饰的注解,
该类型的注解信息只会保留在.java源码里,源码经过编译后,注解信息会被丢弃,不会保留在编译好的.class文件中。
编译时注解:
在定义注解接口时,使用@Retention(RetentionPolicy.CLASS)修饰的注解,
该注解的注册信息会保留在.java源码里和.class文件里,在执行的时候,会被Java虚拟机丢弃,不会加载到虚拟机种。
运行时注解:
在定义注解接口时,使用@Retention(RetentionPolicy.RUNTIME)修饰的注解,
Java虚拟机在运行期也保留注解信息,可以通过反射机制读取注解的信息(.java源码,.class文件和执行的时候都有注解的信息)
3⃣️@Documented:表示被修饰的注解应该被包含在被注解项的文档中。
例如用JavaDoc生成的文档
4⃣️@Inherited:表示该注解可以被子类继承的。
5⃣️@Repeatable:表示这个注解可以在同一个项上面应用多次
不过这个注解是在Java8中才引入的,前面四个元注解都是在Java5中就已经引入的。
2. 反射+运行时注解实现
这里只是基本使用
更多可以看Android中的自定义注解(反射实现-运行时注解)
第一步:创建自定义注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface ContentView {
int value();
}
第二步:使用自定义注解
@ContentView(R.layout.activity_main)
public class MainActivity extends BaseActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
injectContentView(this); //在该方法中进行反射
}
}
第三步:使用反射来处理注解
private void injectContentView(Activity activity) {
Class clazz = activity.getClass();
//如果ContentView这个注解使用了
if (clazz.isAnnotationPresent(ContentView.class)) {
// 得到activity这个类的ContentView注解
ContentView contentView = (ContentView) clazz.getAnnotation(ContentView.class);
// 得到注解的值
int layoutId = contentView.value();
// 使用反射调用setContentView
try {
Method method = clazz.getMethod("setContentView", int.class);
method.setAccessible(true);
method.invoke(activity,layoutId);
} catch (Exception e) {
e.printStackTrace();
}
}
}