android apt最新版本,Android APT

Android APT

文章目录

APT annotation processing tool 注解处理工具

注解类型

注解语法

注解通过@interface关键字来定义

@Retention(RetentionPolicy.CLASS)

@Target({ElementType.FIELD, ElementType.TYPE})

public @interface MyAnnotation {}

Java中总共有5中元注解:@Retention,@Documented,@Target,@Inherited,@Repeatable。下面分别介绍它们:

@Retention

用来说明注解的存活时间,有三种取值:

RetentionPolicy.SOURCE:注解只在源码阶段保留,编译器开始编译时它将被丢弃忽视

RetentionPolicy.CLASS:注解会保留到编译期,但运行时不会把它加载到JVM中

RetentionPolicy.RUNTIME:注解可以保留到程序运行时,它会被加载到JVM中,所以程序运行过程中可以获取到它们

例如我们常用的ButterKnife 使用的就是编译时期的注解,在编译时期通过javapoet生成对对应的代码

@Target

指定注解可作用的目标,取值如下:

ElementType.PACKAGE:可作用在包上

ElementType.TYPE:可作用在类、接口、枚举上

ElementType.ANNOTATION_TYPE:可以作用在注解上

ElementType.FIELD:可作用在属性上

ElementType.CONSTRUCTOR:可作用在构造方法上

ElementType.METHOD:可作用在方法上

ElementType.PARAMETER:可作用在方法参数上

ElementType.LOCAL_VARIABLE:可作用在局部变量上,例如方法中定义的变量

它接收一个数组作为参数,即可以指定多个作用对象,就像上面的Demo:

@Target({ElementType.FIELD, ElementType.TYPE})

@Documented

从名字可知,这个注解跟文档相关,它的作用是能够将注解中的元素包含到Javadoc中去。

@Inherited

Inherited是继承的意思,但并不是注解本身可被继承,而是指一个父类SuperClass被该类注解修饰,那么它的子类SubClass如果没有任何注解修饰,就会继承父类的这个注解。

举个栗子:

@Inherited

@Target(ElementType.Type)

@Retention(RetentionPolicy.RUNTIME)

public @interface Test {}

@Test

public class A {}

public class B extens A {}

解释:注解Test被@Inherited修饰,A被Test修饰,B继承A(B上又无其他注解),那么B就会拥有Test这个注解。

@Repeatable

这个词是可重复的意思,它是java1.8引入的,算一个新特性。

什么样的注解可以多次应用来呢,通常是注解可以取多个值,举个栗子:

Person[] value();

}

@Repeatable(Persons.class)

public @Interface Person {

String role() default ""

}

@Person("artist")

@Person("developer")

@Person("superman")

public class Me {}

解释:@Person被@Repeatable修饰,所以Person可以多次作用在同一个对象Me上,而Repeatable接收一个参数,这个参数是个容器注解,用来存放多个@Person。

注解的处理

运行时注解的处理

运行时的注解处理,一般是通过反射的方式获取到注解,然后进行自己想要的 处理,比如EventBus 的 线程处理的注解,在主线程或子线程,通过反射后在对应的线程里面进行处理!

例如

/**

* 解析注解InjectView

*

* @param activity 使用InjectView的目标对象

*/

public static void inject(Activity activity) {

Field[] fields = activity.getClass().getDeclaredFields();

//通过该方法设置所有的字段都可访问,否则即使是反射,也不能访问private修饰的字段

AccessibleObject.setAccessible(fields, true);

for (Field field : fields) {

boolean needInject = field.isAnnotationPresent(InjectView.class);

if (needInject) {

InjectView anno = field.getAnnotation(InjectView.class);

int id = anno.id();

if (id == -1) continue;

View view = activity.findViewById(id);

Class fieldType = field.getType();

try {

//把View转换成field声明的类型

field.set(activity, fieldType.cast(view));

} catch (Exception e) {

Log.e(InjectView.class.getSimpleName(), e.getMessage());

}

}

}

}

编译时注解的处理

编译时注解 需要注解处理器来协助处理对应的注解,一般情况下我们通过处理器获取注解之后通过javapoet来生成我们想要的文件,例如ButterKnife在编译时期就生成了findviewbyid的文件.

处理步骤如下:

annotation 和 AbstractProcessor需要建在两个不同的moudle中

继承 AbstractProcessor

@AutoService(Processor.class) //自动为我们注册annotation否则需要手动在META_INF下面手动注册

public class MyProcessor extends AbstractProcessor

{

private Types mTypeUtils;

private Elements mElementUtils;

private Filer mFiler;

private Messager mMessager;

@Override

public synchronized void init(ProcessingEnvironment processingEnvironment)

{

super.init(processingEnvironment);

//初始化我们需要的基础工具

mTypeUtils = processingEnv.getTypeUtils();

mElementUtils = processingEnv.getElementUtils();

mFiler = processingEnv.getFiler();

mMessager = processingEnv.getMessager();

}

@Override

public SourceVersion getSupportedSourceVersion()

{

//支持的java版本

return SourceVersion.latestSupported();

}

@Override

public Set getSupportedAnnotationTypes()

{

//支持的注解

Set annotations = new LinkedHashSet<>();

annotations.add(ZyaoAnnotation.class.getCanonicalName());

return annotations;

}

@Override

public boolean process(Set extends TypeElement> set, RoundEnvironment roundEnvironment)

{

//这里开始处理我们的注解解析了,以及生成Java文件

return false;

}

}

javapoet

例如我们想构建一个Activity

public static void main(String[] args){

//构建类

TypeSpec.Builder classBuild=TypeSpec.classBuilder("HomeActivity")

.addModifiers(Modifier.PUBLIC)

.superclass(ClassName.get("android.app","Activity"));

//构建方法

MethodSpec onCreate= MethodSpec.methodBuilder("onCreate")

.addAnnotation(ClassName.get("java.lang","Override"))

.addModifiers(Modifier.PROTECTED)

.addParameter(ClassName.get("android.os","Bundle"),"savedInstanceState")

.addStatement("super.onCreate(savedInstanceState)")

.addStatement("setContentView(R.layout.activity_main)")

.build();

//构建 文件

JavaFile javaFile= JavaFile.builder("com.comers.processor",classBuild.addMethod(onCreate).build()).build();

//写文件

try {

javaFile.writeTo(new File("/Volumes/world/works/NewFrame/app/src/main/java/com/comers/shenwu/kotlin"));

} catch (IOException e) {

e.printStackTrace();

}

}

标签:处理,APT,class,Person,注解,Android,ElementType,public

来源: https://blog.csdn.net/heimaer/article/details/93882148

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值