android studio 注解处理应用
1.AbstractProcessor类介绍
在eclipse上能够利用注释处理高效率的处理代码,同样也能用于Android studio上。
javax.annotation.processing.AbstractProcessor
是一个抽象类,位于javax.annotation.processing包,无关ide。通过实现
public abstract boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv)
处理源码上所标注注释。
2.注释的分类
按照功能,注释分为3类:
[email protected](RetentionPolicy.SOURCE),不需要记录在类文件
[email protected](RetentionPolicy.CLASS) ,需要记录在类文件,但在运行中并不需要保留
[email protected](RetentionPolicy.RUNTIME) ,需要记录在类文件,并在运行中需要保留
c类能够在运行时通过反射方式调用处理,灵活应用,但需要牺牲一定的性能,和不能够进行混淆丢失原有信息,缺乏安全性。
AbstractProcessor通过处理注释并不会影响性能,也完全可以正常混淆。
3.build.gradle配置
在模块dependencies中,添加provided 注释库(包含所有的@interface类),添加annotationProcessor 注释处理库(包含AbstractProcessor类)
一个完整的模块build.gradle例子
apply plugin: 'com.android.application'
android {
compileSdkVersion 26
buildToolsVersion "26.0.0"
defaultConfig {
applicationId "cn.zhg.test.annotations"
minSdkVersion 21
targetSdkVersion 26
versionCode 1
versionName "0.9.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
provided project(':libannotations')
annotationProcessor project(':processor')
}
项目目录结构为
4.注释类库
新建libannotations java库模块,如这里创建一个InjectParcel注释用于,将实体类自动实现Parcel,
package cn.zhg.test.annotations;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.CLASS)
@Target({ ElementType.TYPE})
public @interface InjectParcel
{
/**
* 指定生成类名
* @return
*/
String value() default "";
}
@Target({ ElementType.TYPE})指定只能用于类上,@Retention(RetentionPolicy.CLASS) 不需要在运行时使用
5.注释处理类
新建Processor java模块,在main下创建resources文件夹,在main\resources\META-INF\services\创建javax.annotation.processing.Processor文件指定处理类,处理类TestInjectProcessor继承javax.annotation.processing.AbstractProcessor类。
@SupportedAnnotationTypes("cn.zhg.test.annotations.*")
@SupportedSourceVersion(SourceVersion.RELEASE_6)
public class TestInjectProcessor extends AbstractProcessor
指定支持版本和注释类,在process中获取所有需要处理的注释public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment)
{
log("正在处理...");
Set<? extends Element> annotations = roundEnvironment.getElementsAnnotatedWith(InjectParcel.class);
获取目标类的信息TypeElement classElement = (TypeElement) ele;
String packageName = elementUtils.getPackageOf(classElement).getQualifiedName().toString();//包名
String className = classElement.getQualifiedName().toString();//全名
String simpleName = classElement.getSimpleName().toString();//简名
String targetClassName=simpleName+"Parcel";//生成类的名称
InjectParcel an = classElement.getAnnotation(InjectParcel.class);
if(!an.value().isEmpty())
{
targetClassName=an.value();
}
通过processingEnv.getFiler()#createSourceFile创建源码JavaFileObject jfo = processingEnv.getFiler().createSourceFile(packageName+"."+targetClassName);
try( Writer writer = jfo.openWriter())
{
//写入源码
}
每次构建,源码都会生成在{ProjectDir}/{ModuleName}/build/generated/source/apt/{BuildVar}6.结尾
完整源码