android APT 使用

2020-08-07 15:08:01 浏览数 (1)

什么是 APT

APT(Annotation Processing Tool)即注解处理器,是一种处理注解的工具.简单来说就是在编译期,根据代码中的注解依据相应的规则生成.java文件.

使用
1.创建 自定义注解
代码语言:javascript复制
@Retention(RetentionPolicy.CLASS)
@Target({ElementType.TYPE, ElementType.FIELD})
public @interface JetInject {
   String value() default "";
}

@Retention(RetentionPolicy.CLASS)
@Target({ElementType.TYPE, ElementType.FIELD})
public @interface IRouter {
   /**
    * 该参数当前仅仅支持在activity中使用,表示路由列表
    * @return
    */
   String[] value() default {};
}
2.创建 java-library类型的 module 作为 compiler
  • 自定义 AbstractProcessor,并且用@AutoService注解标记AutoService会自动在META-INF文件夹下生成Processor配置信息文件,该文件里就是注解处理器的全称
代码语言:javascript复制
com.xxx.appcompiler.compiler.Compiler

自动生成如下文件

代码语言:javascript复制
app.compiler/build/classes/java/main/META-INF/services/javax.annotation.processing.Processor
//javax.annotation.processing.Processor 内容如下:
com.xxx.appcompiler.compiler.Compiler

如果不使用 Google 的

代码语言:javascript复制
com.google.auto.service:auto-service

这个库,则需要写如下代码:

代码语言:javascript复制
1.需要在 processors 库的 main 目录下新建 resources 资源文件夹
2.在 resources文件夹下建立 META-INF/services 目录文件夹
3.在 META-INF/services 目录文件夹下创建 javax.annotation.processing.Processor 文件
4.在 javax.annotation.processing.Processor 文件写入注解处理器的全称,包括包路径
com.xxx.appcompiler.compiler.Compiler
  • Compiler类内容
代码语言:javascript复制
@AutoService(Processor.class)
public class Compiler extends AbstractProcessor {
   //process方法会执行多次 这个 flag 用来 保证执行一次
   private boolean isFirst;

   @Override
   public Set<String> getSupportedAnnotationTypes() {
       //将我们自定义的注解添加Set集合
       Set<String> types = new LinkedHashSet<>();
       types.add(JetInject.class.getCanonicalName());
       types.add(IRouter.class.getCanonicalName());
       types.add(JetInit.class.getCanonicalName());
       return types;
  }

   @Override
   public SourceVersion getSupportedSourceVersion() {
       return SourceVersion.latestSupported();
  }

   @Override
   public synchronized void init(ProcessingEnvironment processingEnvironment) {
       super.init(processingEnvironment);
       ProcessingManager manager = ProcessingManager.get();
       manager.setElementUtils(processingEnv.getElementUtils());
       manager.setFiler(processingEnv.getFiler());
       manager.setMessager(processingEnv.getMessager());
       manager.setTypeUtils(processingEnv.getTypeUtils());
  }

   @Override
   public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnv) {

       if (isFirst) {
           return false;
      }
       processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, "---------jet begin --------------------");
       isFirst = true;
       EleParser.getInstance().initPreCode();

       Set<? extends Element> elements = roundEnv.getElementsAnnotatedWith(JetInject.class);
       Set<? extends Element> routers = roundEnv.getElementsAnnotatedWith(IRouter.class);
       if (!init(roundEnv)) {
           return true;
      }
       for (Element ele : elements) {
           if (ele.getKind() == ElementKind.FIELD) {
               EleParser.getInstance().parser(processingEnv, ele, false, true);
          } else if (ele.getKind() == ElementKind.CLASS) {
               EleParser.getInstance().parser(processingEnv, ele, true, true);
          }
      }
       for (Element ele : routers) {
           if (ele.getKind() == ElementKind.CLASS) {
               EleParser.getInstance().parser(processingEnv, ele, true, false);
          }
      }
       //使用javapoet生成代码
       EleParser.getInstance().build();
       return true;
  }
}

生成的代码路径

代码语言:javascript复制
app/build/generated/source/apt/debug/com/xxx/androidcompileractivity/JetInitializer.java

更多内容 欢迎关注公众号

0 人点赞