android组件化 APT高级用法javaPoet

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/coderinchina/article/details/97056728

什么是JavaPoet,就是APT+javaPoet =超级利刃

javaPoet是square公司推出的开源代码生成框架,提供api生成.java 源文件,这个框架功能非常实用,也是我们习惯的面向对象oop思想 可以很方便的使用它根据注解生成代码 通过这种自动化生成代码的方式  可以让我们更加简洁优雅的方式来替代复杂的工作

它的github地址 javaPoet

它的官网有很多例子 可以跟着写

javaPoet和前一篇博客生成文件的顺序不一样,javaPoet是倒着来的

javaPoet常用的8个类

这些写多了就记住了

javaPoet字符串格式化规则

新建一个项目JavaPoetTest 二个library 一个是annotation  一个是compiler

跟上篇博客配置是一样的,这就不再说了,直接看下process()方法,看下javaPoet github地址 它有demo,先把demo练习几篇就会了

比如要创建这个类

package com.example.helloworld;

public final class HelloWorld {
  public static void main(String[] args) {
    System.out.println("Hello, JavaPoet!");
  }
}

官网给的代码

 @Override
    public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {
        if(set.isEmpty()){
            return false;
        }

        messager.printMessage(Diagnostic.Kind.NOTE, "1111111");
        MethodSpec main = MethodSpec.methodBuilder("main")//main是方法名
                .addModifiers(Modifier.PUBLIC, Modifier.STATIC)//添加方法修饰符
                .returns(void.class)//方法返回值
                .addParameter(String[].class, "args")//行参类型和行参变量名字
                .addStatement("$T.out.println($S)", System.class, "Hello, JavaPoet!")//这是方法里面的内容 $T $s表示类和字符串 跟String.format("%d几岁",%d)跟String的格式一样
                .build();
        //这是添加类信息
        TypeSpec helloWorld = TypeSpec.classBuilder("HelloWorld")//添加类名字
                .addModifiers(Modifier.PUBLIC, Modifier.FINAL)//类修饰符
                .addMethod(main)//添加类方法
                .build();
        //这是把该类放到对应的包中
        JavaFile javaFile = JavaFile.builder("com.example.helloworld", helloWorld)
                .build();
        messager.printMessage(Diagnostic.Kind.NOTE, "22222");
        //写到控制台 方便查看
        try {
            javaFile.writeTo(System.out);
        } catch (IOException e) {

            e.printStackTrace();
        }
        try {
            //这个必须得调用 不然生不了文件
            javaFile.writeTo(filer);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return true;
    }

然后make module app下就行了,看下build控制台

再看下app. module下的build目录下查看生成的文件

现在再来写我们自己写的ARouter注解处理器要生成的文件,如下

public class MainActivity$$ARouter {
  public static Class findTargetClass(String path) {
    return path.equals("/app/MainActivity") ? MainActivity.class : null;
  }
}

process()方法中的代码

 @Override
    public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {
        if(set.isEmpty()){
            return false;
        }
        // 获取所有带ARouter注解的 类节点
        Set<? extends Element> elements = roundEnvironment.getElementsAnnotatedWith(ARouter.class);
        // 遍历所有类节点
        for (Element element : elements) {
            // 通过类节点获取包节点(全路径:com.netease.xxx)
            String packageName = elementUtils.getPackageOf(element).getQualifiedName().toString();
            messager.printMessage(Diagnostic.Kind.NOTE, "packageName="+packageName);
            // 获取简单类名
            String className = element.getSimpleName().toString();
            messager.printMessage(Diagnostic.Kind.NOTE, "className="+className);

//            messager.printMessage(Diagnostic.Kind.NOTE, "被注解的类有:" + className);
            // 最终想生成的类文件名
            String finalClassName = className + "$$ARouter";

            // 高级写法,javapoet构建工具,参考(https://github.com/JakeWharton/butterknife)
            try {
                // 获取类之上@ARouter注解的path值
                ARouter aRouter = element.getAnnotation(ARouter.class);

                // 构建方法体
                MethodSpec method = MethodSpec.methodBuilder("findTargetClass") // 方法名
                        .addModifiers(Modifier.PUBLIC, Modifier.STATIC)
                        .returns(Class.class) // 返回值Class<?>
                        .addParameter(String.class, "path") // 参数(String path)
                        // 方法内容拼接:
                        // return path.equals("/app/MainActivity") ? MainActivity.class : null
                        .addStatement("return path.equals($S) ? $T.class : null",
                                aRouter.path(), ClassName.get((TypeElement) element))
                        .build(); // 构建

                // 构建类
                TypeSpec type = TypeSpec.classBuilder(finalClassName)
                        .addModifiers(Modifier.PUBLIC) //, Modifier.FINAL)
                        .addMethod(method) // 添加方法体
                        .build(); // 构建

                // 在指定的包名下,生成Java类文件
                JavaFile javaFile = JavaFile.builder(packageName, type)
                        .build();
                javaFile.writeTo(System.out);
                javaFile.writeTo(filer);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        return true;
    }

ok,

猜你喜欢

转载自blog.csdn.net/coderinchina/article/details/97056728