美文网首页面试
Android APT使用

Android APT使用

作者: 人称老黄 | 来源:发表于2022-06-09 14:20 被阅读0次

    APT是什么?有什么用?

    APT(Annotation Processing Tool)即注解处理器,在编译的时候可以处理注解然后搞一些事情,也可以在编译时生成一些文件之类的
    APT编译的时候 处理注解
    APT传统方式 生成java文件
    APT JavaPoet方式 生成java文件
    ButterKnife和EventBus都使用了APT技术

    image.png image.png

    传统方式:可读性强
    javaPoet:看起来费劲

    APT使用

    1.创建arouter-annotation的java工程,这个工程用来写注解


    image.png

    2.创建ARouter注解

    @Target({ElementType.TYPE})  //作用域在类上面
    @Retention(RetentionPolicy.CLASS)  //编译期
    public @interface ARouter {
        String path();
    
        String group() default  "" ;
    }
    

    3.创建compiler的java工程,这个工程用来写注解处理器


    image.png

    4.在build.gradle增加JavaPoet和autoService

    dependencies{
        implementation fileTree(dir: 'libs', include: ['*.jar'])
          //路由
        compileOnly 'com.google.auto.service:auto-service:1.0-rc4'
        annotationProcessor 'com.google.auto.service:auto-service:1.0-rc4'
    
        implementation project(":arouter-annotation")
        //帮助我们通过类调用的形式来生成Java代码[JavaPoet]
        implementation "com.squareup:javapoet:1.10.0"
    }
    

    5.在compiler工程里面创建AbstractProcessor

    @AutoService(Processor.class) //启用服务
    @SupportedAnnotationTypes({"com.im.arouter_annotation.ARouter"}) 
    @SupportedSourceVersion(SourceVersion.RELEASE_7)
    public class  ARouterProcessor extends AbstractProcessor {
        //在编译期干活
        @Override
        public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {
    
            return false;
        }
    }
    

    6.在app的build.gradle里面关联arouter-annotation

        dependencies {
        implementation project(":arouter-annotation")
    
    }
    

    7.在ARouterProcessor里面添加Elements,Types ,Messager ,Filer属性

    @AutoService(Processor.class) //启用服务
    @SupportedAnnotationTypes({"com.im.arouter_annotation.ARouter"})
    @SupportedSourceVersion(SourceVersion.RELEASE_7)
    public class  ARouterProcessor extends AbstractProcessor {
        //操作Element的工具类(类,函数,属性,其实都是Element )
        private Elements elements;
    
        //type( 类信息)的工具类,包含用于操作TypeMirror的工具方法
        private Types types;
    
        //用来打印日志相关信息
        private Messager messager;
    
        //文件生成器, 类资源等,就是最终要生成的文件是需要Filer来完成的
        private Filer filer;
    
        @Override
        public synchronized void init(ProcessingEnvironment processingEnv) {
            super.init(processingEnv);
            elements=processingEnv.getElementUtils();
            types=processingEnv.getTypeUtils();
            messager=processingEnv.getMessager();
            filer=processingEnv.getFiler();
        }
    
        //在编译期干活
        @Override
        public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {
            return false;
        }
    }
    

    8.在app的build.gradle添加配置

    defaultConfig {
            //传参数
            javaCompileOptions {
                annotationProcessorOptions {
                    arguments = ["TestName": "这是测试结果"]
                }
            }
            kapt {
                arguments {
                    arg("TestName", "这是测试结果")
                }
            }
        }
    

    9.在ARouterProcessor的init方法里面通过TestName拿到value

    @AutoService(Processor.class) //启用服务
    @SupportedAnnotationTypes({"com.im.arouter_annotation.ARouter"})
    @SupportedSourceVersion(SourceVersion.RELEASE_7)
    //接收参数
    @SupportedOptions("TestName")
    public class  ARouterProcessor extends AbstractProcessor {
        //操作Element的工具类(类,函数,属性,其实都是Element )
        private Elements elements;
    
        //type( 类信息)的工具类,包含用于操作TypeMirror的工具方法
        private Types types;
    
        //用来打印日志相关信息
        private Messager messager;
    
        //文件生成器, 类资源等,就是最终要生成的文件是需要Filer来完成的
        private Filer filer;
    
        @Override
        public synchronized void init(ProcessingEnvironment processingEnv) {
            super.init(processingEnv);
    
            elements=processingEnv.getElementUtils();
            types=processingEnv.getTypeUtils();
            messager=processingEnv.getMessager();
            filer=processingEnv.getFiler();
    
            String value=processingEnv.getOptions().get("TestName");
            //需要注意的是不能使用Diagnostic.Kind.ERROR  ,如果想让注解处理器抛出异常就使用Diagnostic.Kind.ERROR
            messager.printMessage(Diagnostic.Kind.NOTE,"测试一下===="+value);
        }
    
      
        //在编译期干活
        @Override
        public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {
            messager.printMessage(Diagnostic.Kind.NOTE,"执行process");
            return false;
        }
    }
    

    9.使用Make Project


    image.png
    image.png

    只有在用到ARouter注解的时候ARouterProcessor才会执行里面的方法

    9.通过APT创建Test类

    @AutoService(Processor.class) //启用服务
    @SupportedAnnotationTypes({"com.im.arouter_annotation.ARouter"})
    @SupportedSourceVersion(SourceVersion.RELEASE_7)
    //接收参数
    @SupportedOptions("TestName")
    public class  ARouterProcessor extends AbstractProcessor {
        //操作Element的工具类(类,函数,属性,其实都是Element )
        private Elements elements;
    
        //type( 类信息)的工具类,包含用于操作TypeMirror的工具方法
        private Types types;
    
        //用来打印日志相关信息
        private Messager messager;
    
        //文件生成器, 类资源等,就是最终要生成的文件是需要Filer来完成的
        private Filer filer;
    
        @Override
        public synchronized void init(ProcessingEnvironment processingEnv) {
            super.init(processingEnv);
    
            elements=processingEnv.getElementUtils();
            types=processingEnv.getTypeUtils();
            messager=processingEnv.getMessager();
            filer=processingEnv.getFiler();
    
            String value=processingEnv.getOptions().get("TestName");
            //需要注意的是不能使用Diagnostic.Kind.ERROR  ,如果想让注解处理器抛出异常就使用Diagnostic.Kind.ERROR
            messager.printMessage(Diagnostic.Kind.NOTE,"测试一下===="+value);
        }
    
        //在编译期干活
        @Override
        public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {
            messager.printMessage(Diagnostic.Kind.NOTE,"执行process");
            /*
                package com.example.helloworld;
    
                public final class HelloWorld {
                public static void main(String[] args) {
                System.out.println("Hello, JavaPoet!");
                }
                }
            * */
            //拿到注解
            Set<? extends Element> ARouters = roundEnvironment.getElementsAnnotatedWith(ARouter.class);
            for (Element aRouter : ARouters) {
                //先写方法  类 和包
    
                //生成一个public static void main(String[] args)的方法
                //"$T.out.println($S)" $T相当于一个占位符 和System.class 对应
                //"$S相当于一个占位符 和Hello, JavaPoet!对应
                MethodSpec methodSpec=MethodSpec.methodBuilder("main").addModifiers(Modifier.PUBLIC
                ,Modifier.STATIC).returns(void.class).addParameter(String[].class,"args").
                        addStatement("$T.out.println($S)",System.class,"Hello, JavaPoet!").
                        build();
                //创建一个 public final class Test 类
                // 并且把methodSpec方法传进去
                TypeSpec typeSpec = TypeSpec.classBuilder("Test").
                        addMethod(methodSpec).addModifiers(Modifier.PUBLIC,Modifier.FINAL).
                        build();
    
                JavaFile javaFile = JavaFile.builder("com.compiler.test", typeSpec).build();
    
                //生成文件
                try {
                    javaFile.writeTo(filer);
                } catch (IOException e) {
                    e.printStackTrace();
                    messager.printMessage(Diagnostic.Kind.NOTE,"javaFile:"+e.getMessage());
    
                }
            }
            return false;  //一般不用管这里的返回值
        }
    }
    
    image.png
    image.png

    相关文章

      网友评论

        本文标题:Android APT使用

        本文链接:https://www.haomeiwen.com/subject/wwyvertx.html