【Android APT】编译时技术 ( 开发编译时注解 )

举报
韩曙亮 发表于 2022/01/10 23:39:48 2022/01/10
【摘要】 文章目录 一、编译时注解二、编译时注解 使用三、注解的保留时间四、博客资源 一、编译时注解 上一篇博客 【Android APT】编译时技术 ( 编译时注解 和 注...





一、编译时注解



上一篇博客 【Android APT】编译时技术 ( 编译时注解 和 注解处理器 依赖库 ) 中创建并配置了 annotation 编译时注解 依赖库annotation-compiler 注解处理器 依赖库 ;

本博客开始进行开发 编译时注解 依赖库 ;


开发 annotation 编译时注解 依赖库 ;

右键点击包名 , 选择 " New / Java Class " 选项 ,

在这里插入图片描述

在弹出的对话框中 , 选择 " Annotation " 注解对话框 , 然后输入注解名称 BindView ,

在这里插入图片描述

注解源码开发 :

package kim.hsl.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.CLASS)
public @interface BindView {
    int value();
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

元注解解析 :

使用 @Target(ElementType.FIELD) 元注解标注该 BindView 注解 , 说明该 @BindView 注解是作用于成员变量的 ;

使用 @Retention(RetentionPolicy.CLASS) 标注 BindView 注解 , 说明该注解是 编译时注解 ;


注解属性解析 :

使用 value 作为注解属性名 , 并且只有一个 注解属性 , 因此该注解在使用的时候 , 为注解属性赋值可以省略 " value = " , 直接传入注解属性值 ;





二、编译时注解 使用



注释掉之前的 ButterKnife 的 编译时注解 和 注解处理器 , 使用应用中自己开发的 编译时注解注解处理器 ;

build.gradle 构建脚本 依赖库相关配置 如下 :

dependencies {

    //implementation 'com.jakewharton:butterknife:10.2.3'
    //annotationProcessor 'com.jakewharton:butterknife-compiler:10.2.3'

    annotationProcessor project(path: ':annotation-compiler')
    implementation project(path: ':annotation')
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

在 MainActivity 中模仿 ButterKnife 使用 @BindView 注解 , 这是我们自定义的注解 ;

package kim.hsl.apt;

import android.os.Bundle;
import android.widget.TextView;

import androidx.appcompat.app.AppCompatActivity;

import kim.hsl.annotation.BindView;

public class MainActivity extends AppCompatActivity {

    @BindView(R.id.hello)
    TextView hello;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //hello.setText("ButterKnife");
    }
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

下一步开始使用 注解处理器 , 处理上述注解 ;

注解处理器 工作机制 : 当程序在编译时 , 执行注解处理器 , 注解处理器会搜索整个程序中 , 使用到 BindView 注解的位置 , 并获取注解的相关信息 , 所在字节码文件 , 作用位置 ( 类 / 方法 / 字段等 ) ;





三、注解的保留时间



注解分类 :

① 源码期注解 : 注解保留到源码阶段 , 只有当类是 .java 文件时才能看到 , 一旦编译成 .class 字节码文件 , 该注解就消失了 , 如 @Override 仅在编译时查看父类是否有该方法 ;

② 编译时注解 : 注解保留到字节码阶段 ;

③ 运行时注解 : 注解保留到运行时 ;


源码期注解 与 编译时注解 对比示例 :

查看 MainActivity.java 源码 : 该源码中有两个注解 @BindView 和 @Override 两个注解 ;
在这里插入图片描述


查看 BindView 注解的源码如下 , 其中 BindView 注解是被 @Retention(RUNTIME) 修饰的 , 说明该注解是 运行时注解 , 该注解需要从源码 到 字节码 一直保留 , 知道运行时才开始解析该注解 ;

@Retention(RUNTIME) @Target(FIELD)
public @interface BindView {
  /** View ID to which the field will be bound. */
  @IdRes int value();
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5

查看 Override 注解的源码如下 , 该注解被 @Retention(RetentionPolicy.SOURCE) 修饰 , 说明该注解是 源码期注解 , 注解信息仅在源码阶段保存 , 一旦编译成字节码文件 , 高注解就被删除了 ;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}

  
 
  • 1
  • 2
  • 3
  • 4

编译应用后 , 查看 MainActivity.class 字节码文件 , 该字节码文件在 " APT\app\build\intermediates\javac\debug\classes\kim\hsl\apt " 目录下 ;

字节码文件中的 @Override 注解已经消失 , @BindView 注解还存在 ;

@Override 注解是 源码期注解 , 只保留到源码期 , 编译时使用该注解 , 编译完成后 , 该注解就被删除了 ;

@BindView 注解 是 运行时注解 , 该注解需要在运行时使用 , 需要一直保留到运行时 ;
在这里插入图片描述





四、博客资源



博客源码 :

文章来源: hanshuliang.blog.csdn.net,作者:韩曙亮,版权归原作者所有,如需转载,请联系作者。

原文链接:hanshuliang.blog.csdn.net/article/details/117046197

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

举报
请填写举报理由
0/200