美文网首页
Android开发 APT技术

Android开发 APT技术

作者: 雨来 | 来源:发表于2021-06-09 16:17 被阅读0次

    APT

    annotation process Tool 简称apt 也就是注解处理器的意思 像android中的三方库 最新版的eventBus Dagger2 等都是使用的这个技术 首先我们要 懂java中的注解的概念

    什么是注解annotation

    java中的注解 是描述java代码的元数据 它是不会影响java代码的运行的,但我们可以获取注解上的数值参于一定的计算和逻辑的

    通过APT可以做什么

    我们可以通过apt帮我们生成 按我们的规则制定的 java类文件

    下面是例子可以直接运行(虽然没有什么意义但可以生成文件 逻辑逻辑大家可以按你们的业务来)

    结构图:(3是依赖 1和2)

    1和2都是java library


    image.png
    image.png image.png image.png

    具体代码:

    Annotation library

    provider接口 这个接口没有什么用

    public interface Provider {
    }
    

    RouteAnnotation 这个注解

    @Retention(RetentionPolicy.CLASS)
    @Target(ElementType.TYPE)
    public @interface RouteAnnotation {
        String name() default "MainActivity";
    }
    
    Annotation-complier 这个 library

    注解处理器 AnnotationProcess 类

    package com.www.annotation_complier;
    
    /**
     * @author yulai
     * @time:
     */
    
    
    import com.google.auto.service.AutoService;
    import com.squareup.javapoet.JavaFile;
    import com.squareup.javapoet.MethodSpec;
    import com.squareup.javapoet.TypeSpec;
    import com.www.annotation.Provider;
    import com.www.annotation.RouteAnnotation;
    
    import java.io.IOException;
    import java.util.HashMap;
    import java.util.LinkedHashSet;
    import java.util.Set;
    
    import javax.annotation.processing.AbstractProcessor;
    import javax.annotation.processing.Filer;
    import javax.annotation.processing.ProcessingEnvironment;
    import javax.annotation.processing.Processor;
    import javax.annotation.processing.RoundEnvironment;
    import javax.lang.model.SourceVersion;
    import javax.lang.model.element.Element;
    import javax.lang.model.element.Modifier;
    import javax.lang.model.element.TypeElement;
    
    //这个一定要写
    @AutoService(Processor.class)
    public class AnnotationProcess extends AbstractProcessor {
    
        private Filer mFiler; //这个filer类主要是为了生成java文件
    
        @Override
        public synchronized void init(ProcessingEnvironment processingEnv) {
            super.init(processingEnv);
            mFiler = processingEnv.getFiler();
        }
    
        @Override
        public SourceVersion getSupportedSourceVersion() {
    //        return super.getSupportedSourceVersion();
            return SourceVersion.RELEASE_8;
        }
    
        @Override
        public Set<String> getSupportedAnnotationTypes() {
    //        return super.getSupportedAnnotationTypes();
    
            LinkedHashSet<String> types = new LinkedHashSet<>();
            types.add(RouteAnnotation.class.getCanonicalName());
    
            return types; //这个注解处理器只处理批定的注解(也就是我们自己定义的注解) 通过types.add()方法添加
        }
    
        @Override
        public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
    
            HashMap<String, String> nameMap = new HashMap<>();
    
    //        拿到所有RouteAnnotation注解标注的类
            Set<? extends Element> annotationElements = roundEnv.getElementsAnnotatedWith(RouteAnnotation.class);
    
            for (Element element : annotationElements) {
    
                RouteAnnotation annotation = element.getAnnotation(RouteAnnotation.class);
    
                String name = annotation.name();
                nameMap.put(name, element.getSimpleName().toString()); //这个集合中存了注解的name名字同时把当前页面的 类名也拿到了
    
            }
    
            //生成java文件
            generateJavaFile(nameMap);
    
            return true;
        }
    
        private void generateJavaFile(HashMap<String, String> nameMap) {
    
            System.out.println("执行了");
    
            //这是声明了一个修饰符为public的 并且有一个局部变量 routeMap 的HashMap  一个构造方法
            MethodSpec.Builder constructorBuild = MethodSpec.constructorBuilder()
                    .addModifiers(Modifier.PUBLIC)
                    .addStatement("routeMap = new $T<>()", HashMap.class);
    
    
            for (String key : nameMap.keySet()) {
                String name = nameMap.get(key);
                constructorBuild.addStatement("routeMap.put(\"$N\",\"$N\")", key, name); //在 构造方法中会生成 routemap.put的动作
            }
    
            MethodSpec constrouctName = constructorBuild.build();
    
            //一个普通方法
            MethodSpec reouteName = MethodSpec.methodBuilder("getActivityName")
                    .addModifiers(Modifier.PUBLIC)
                    .returns(String.class)
                    .addParameter(String.class, "routeName")
                    .beginControlFlow("if(null==routeMap&&!routeMap.isEmpty())")
                    .addStatement("return (String) routeMap.get(routeName)")
                    .endControlFlow()
                    .addStatement("return \"\"")
                    .build();
    
            //generate class生成一个类
            TypeSpec typeSpec = TypeSpec.classBuilder("AnnotationRoute$Finder")
                    .addModifiers(Modifier.PUBLIC)
                    .addMethod(constrouctName)
                    .addMethod(reouteName)
                    .addSuperinterface(Provider.class)
                    .addField(HashMap.class, "routeMap", Modifier.PRIVATE)
                    .build();
    
            JavaFile javaFile = JavaFile.builder("com.route.page", typeSpec).build();
            try {
                javaFile.writeTo(mFiler);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
    }
    
    

    测试生成的类是否可以调用

     * @author yulai
     * @time:
     */
    @RouteAnnotation(name = "Route_MainActivity")
    public class MainActivity extends AppCompatActivity {
        @Override
        protected void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            new AnnotationRoute$Finder().getActivityName(""); //测试这个类生成了
        }
    }
    
    

    注意gradle插件和gradle的版本 先用这个版本 不要kotlin的插件使用

    image.png

    demo下载地址:
    https://github.com/hwp2009/APT/tree/master

    相关文章

      网友评论

          本文标题:Android开发 APT技术

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