Android 自定义注解

来源:互联网 发布:穿越火线fps优化器 编辑:程序博客网 时间:2024/06/04 21:15

一。按注解处理方式分类

1.1 运行时处理 这个是编译器默认的做法,编译器会通过class文件,逐个逐个的遍历class的属性和方法,即运行时处理1.2 编译时处理编译器会在编译的时候,将注解的属性引入在进行编译

二。基本概念

2.1元注解 @desc{用于修饰定义自定义注解的注解}    **@Target**:表明该自定义注解应该用于什么地方      ElemenetType.CONSTRUCTOR----构造器声明       ElemenetType.FIELD ----域声明(包括 enum 实例)       ElemenetType.LOCAL_VARIABLE---- 局部变量声明       ElemenetType.METHOD----方法声明       ElemenetType.PACKAGE ---- 包声明       ElemenetType.PARAMETER ----参数声明       ElemenetType.TYPE---- 类,接口(包括注解类型)或enum声明     **@Retention**:@desc{表明该自定义注解的生命周期}     RetentionPolicy.SOURCE ----注解只会保留在源文件中(JAVA code),将被编译器丢弃       RetentionPolicy.CLASS ----注解保留在 class 文件中,加载到 JVM 时会被JVM丢弃       RetentionPolicy.RUNTIME VM----注解将保留在运行期,因此可以通过反射机制读取注解的信息。 **@Documented:**@desc{表明该自定义注解可以被 javadoc 工具提取到文档中}**@Inherited:**@desc{允许子类继承父类注解}

三。自定义注解实现

3.1运行时反射 Reflect    @code:    public class InjectActivity extends AppCompatActivity {private int mLayoutId = -1;@Overrideprotected void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    displayInjectLayout();    displayInjectView();}/** * 解析注解view id */private void displayInjectView() {    if (mLayoutId <=0){return ;}    Class<?> clazz = this.getClass();//获取该类的 Class 对象    Field[] fields = clazz.getDeclaredFields();//获得声明的成员变量    for (Field field : fields) {        //判断是否有注解        try {            if (field.getAnnotations() != null) {                if (field.isAnnotationPresent(ViewInject.class)) {//如果属于这个注解                    //为这个控件设置属性                    field.setAccessible(true);//允许修改反射属性                    ViewInject inject = field.getAnnotation(ViewInject.class);                    field.set(this, this.findViewById(inject.value()));                }            }        } catch (Exception e) {            Log.e("wusy", "not found view id!");        }throw new InterruptedException("not found view id!");    }}/** * 注解布局Layout id */private void displayInjectLayout() {    Class<?> clazz = this.getClass();    if (clazz.getAnnotations() != null){        if (clazz.isAnnotationPresent(LayouyInject.class)){            LayouyInject inject = clazz.getAnnotation(LayouyInject.class);            mLayoutId = inject.value();            setContentView(mLayoutId);        }    }}

}

3.2编译时 AnnotationProcessor    3.2.1Android程序的编译流程    标准 java 编译方式    javac(*.java—>*.class){  ProGuard }—>dx(*.class—>*.dex)    1——  javac 工具将 java源代码编译成 .class(java 字节码)    2——  ProGuard 工具读取 Proguard 配置,对 class 文件做压缩和忽略混淆,输出 Proguard mapping    3—— dx 工具将.class文件转化成 classes.dex,若单个 dex 文件方法数超过64K。开启多分包—》classes1.dex  ,classes2.dex。。。。。    jack 编译方式(java Android compiler kit)    Jack(.java—>.jack—>.dex)    参考文章@link{  http://taobaofed.org/blog/2016/05/05/new-compiler-for-android/  }    3.2.2 APT 插件(Annotation Processing Tool)    注解处理器是 javac 内置的一个工具,用于在编译时期扫描和处理注解信息。一个特定的 APT 接收一个 java 源代码或者已编译的 class 字节码作为输入,然后输出一些文件(一般是 java 文件)。使用 apt 可以动态生成代码逻辑,但是 apt 只能生成新的 java 类文件,而不能在旧的 java 类上做修改,所有apt生成的 java 类会和其他 java 代码一起被编译。    3.3.3实现自定义注解处理器        1.新建一个 module,必须设置为 java Library,否则找不到 AbstractProcessor         2.自定义注解处理器,继承@link{ javax.annotation.processing.AbstractProcessor }  虚处理器        ![这里写图片描述](http://img.blog.csdn.net/20170627180911830?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvY2hyaXNtYTY2Ng==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)    3.3.4.声明注解处理器{注册到 JVM}        1、在 processors 库的 main 目录下新建 resources 资源文件夹;        2、在 resources文件夹下建立 META-INF/services 目录文件夹;        3、在 META-INF/services 目录文件夹下创建 javax.annotation.processing.Processor 文件;        4、在 javax.annotation.processing.Processor 文件写入注解处理器的全称,包括包路径;    或者 使用 Google 的 AutoService 注解,AutoService注解处理器是Google开发的,用来生成                       META-INF/services/javax.annotation.processing.Processor 文件的,你只需要在你定义的注解处理器上添加 @AutoService(Processor.class)            compile 'com.google.auto.service:auto-service:1.0-rc2’

在处理器里面添加注解@AutoService(Processors.class)

    3.3.5关于annotations 和 processors 库依赖的问题        a.app 直接依赖 annotations 和 processors 两个 module        compile project(':annotations')        compile project(':processors')       b.android-apt:       app 只依赖 annotations 模块,不用依赖 processors 模块       ![这里写图片描述](http://img.blog.csdn.net/20170627191527434?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvY2hyaXNtYTY2Ng==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)       c.annotationProcessor:       注:一定要移除 apt 的相关配置,不然会冲突,导致 ap 失效       ![这里写图片描述](http://img.blog.csdn.net/20170627191635497?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvY2hyaXNtYTY2Ng==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)