[源代码][1] [1]: https://github.com/chris118/android-annotation
###1) 建一个Java
库来专门放注解,库名为:ptannotation, 注意,这里必须为Java库,不然会找不到javax包下的相关资源
定义注解类 PTRoutRule.java
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.CLASS)
public @interface PTRoutRule {
String[] value();
}
###2) 建一个Java
库工程,库名为:ptcompiler,记得是和存放注解的库分开的。注意,这里必须为Java库,不然会找不到javax包下的相关资源
引入auto-service 和 javapoet
定义 PTProcessor.java
implementation 'com.google.auto.service:auto-service:1.0-rc3'//生成 META-INF/services/javax.annotation.processing.Processor 文件
implementation 'com.squareup:javapoet:1.8.0' //用于产生 .java 源文件的辅助库
implementation project(':ptannotation')
@AutoService(Processor.class)
public class PTProcessor extends AbstractProcessor {
private static final boolean DEBUG = true;
private Messager messager;
private Filer filer;
/**
* init()方法会被注解处理工具调用,并输入ProcessingEnviroment参数。
* ProcessingEnviroment提供很多有用的工具类Elements, Types 和 Filer
* @param processingEnvironment 提供给 processor 用来访问工具框架的环境
*/
@Override
public synchronized void init(ProcessingEnvironment processingEnvironment) {
super.init(processingEnvironment);
messager = processingEnv.getMessager();
filer = processingEnv.getFiler();
}
/**
* 这里必须指定,这个注解处理器是注册给哪个注解的。注意,它的返回值是一个字符串的集合,包含本处理器想要处理的注解类型的合法全称
* @return 注解器所支持的注解类型集合,如果没有这样的类型,则返回一个空集合
*/
@Override
public Set<String> getSupportedAnnotationTypes() {
Set<String> ret = new HashSet<>();
ret.add(PTRoutRule.class.getCanonicalName());
return ret;
}
/**
* 指定使用的Java版本,通常这里返回SourceVersion.latestSupported(),默认返回SourceVersion.RELEASE_6
* @return 使用的Java版本
*/
@Override
public SourceVersion getSupportedSourceVersion() {
return SourceVersion.latestSupported();
}
/**
* 这相当于每个处理器的主函数main(),你在这里写你的扫描、评估和处理注解的代码,以及生成Java文件。
* 输入参数RoundEnviroment,可以让你查询出包含特定注解的被注解元素
* @param annotations 请求处理的注解类型
* @param roundEnvironment 有关当前和以前的信息环境
* @return 如果返回 true,则这些注解已声明并且不要求后续 Processor 处理它们;
* 如果返回 false,则这些注解未声明并且可能要求后续 Processor 处理它们
*/
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnvironment) {
debug("process start------------" + annotations.toString());
if (annotations.isEmpty()) {
return false;
}
//添加init函数
MethodSpec.Builder methodBuilder = MethodSpec.methodBuilder("init")
.addModifiers(Modifier.PUBLIC, Modifier.FINAL, Modifier.STATIC)
.addCode("\n");
// process PTRoutRule
Set<? extends Element> elements = roundEnvironment.getElementsAnnotatedWith(PTRoutRule.class);
for (Element element : elements) {
PTRoutRule router = element.getAnnotation(PTRoutRule.class);
String url = null;
for (String urlValue : router.value()) {
debug(urlValue); //暂时支持一个url
url = urlValue;
}
//添加注解的类
ClassName className = null;
if (element.getKind() == ElementKind.CLASS) {
className = ClassName.get((TypeElement) element);
debug(className.simpleName());
}
if(url == null){
debug("url is null");
}else if(className == null){
debug("className is null");
}else{
if (element.getKind() == ElementKind.CLASS) {
debug("com.hh.ptrouter.PTRouter.Register:" + " url = " + url + " className = " + className);
methodBuilder.addStatement("com.hh.ptrouter.PTRouter.Register($S, $T.class)", url, className);
}
}
methodBuilder.addCode("\n");
}
//创建类
TypeSpec routerMapping = TypeSpec.classBuilder("PTRouterProcessor")
.addModifiers(Modifier.PUBLIC, Modifier.FINAL)
.addMethod(methodBuilder.build())
.build();
//写入文件
try {
JavaFile.builder("com.hh.ptrouter", routerMapping)
.build()
.writeTo(filer);
} catch (Throwable e) {
e.printStackTrace();
}
debug("process end------------" + annotations.toString());
return true;
}
private void error(String error) {
messager.printMessage(Diagnostic.Kind.ERROR, error);
}
private void debug(String msg) {
if (DEBUG) {
messager.printMessage(Diagnostic.Kind.NOTE, msg);
}
}
}
###3) App工程使用注解
annotationProcessor project(':ptcompiler') //替代旧的apt
implementation project(':ptannotation')
@PTRoutRule(value = "putao://home")
public class HomeActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
}
}
###4) 生成文件
Make Project, 在Gradle Console中可以看到具体的调试打印信息,如果以上都成功了,会在目录/Users/admin/src/android/PTApp/app/build/generated/source/apt/debug/com/hh/ptrouter 生成PTRouterProcessor.java