JavaPoet 和 Java 注解在 Android 中的应用

JavaPoet 结合 Java 注解在很多知名的开源库中都应用,例如 Butterknife 和 ARouter.
JavaPoet 是用来生成 .java 文件的,它的使用比较简单,按照官方的示例代码套用就可以了。
Java 的注解,有时间会整理,这里先略过。

我做了一个 Dome 说明它们的应用。
先看一下项目的结构。
这里写图片描述

整个项目包含三个部分:
- app : 主项目,使用我们的注解
- annotationlib: 注解
- javapoetlib: 使用 javaPoet 生成 .java 代码

下面我们一个个来看

1. 注解

我们先生成一个 java library 生成注解, 这里不能选 android library, 命名为 annotationlib.
这里写图片描述

它的 build.gradle 文件我们不用修改, 我们看到它是 java-library

    apply plugin: 'java-library'

    dependencies {
        implementation fileTree(dir: 'libs', include: ['*.jar'])
    }

    sourceCompatibility = "1.7"
    targetCompatibility = "1.7"

创建一个名为 MyAnnotation 的接口文件, 它的内容也是非常简单的

    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.CLASS)
    public @interface MyAnnotation {
        int action() default 0;
    }

2. JavaPoet 生成 .java 文件

同样创建一个 java library, 命名为 javapoetlib, 但是它的 build.gradle 文件,我们要修改

    apply plugin: 'java-library'

    dependencies {
        implementation fileTree(dir: 'libs', include: ['*.jar'])
        compile project(':annotationlib')
        compile 'com.google.auto.service:auto-service:1.0-rc2'
        compile 'com.squareup:javapoet:1.9.0'
    }

    sourceCompatibility = "1.7"
    targetCompatibility = "1.7"

我们添加对刚刚创建的 annotationlib 依赖,同时添加 auto-service 和 javapoet.

我们创建一个 MyProcessor 的文件


@AutoService(Processor.class)  // 需要添加 
public class MyProcessor extends AbstractProcessor {

    private Filer mFiler;
    private Elements mElementUtils;
    private Messager mMessager;


    private static final String PACK_NAME = "com.yxhuang.temp";

    @Override
    public synchronized void init(ProcessingEnvironment processingEnvironment) {
        super.init(processingEnvironment);

        mFiler = processingEnv.getFiler();
        mElementUtils = processingEnv.getElementUtils();
        mMessager = processingEnv.getMessager();

    }

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

    @Override
    public Set<String> getSupportedAnnotationTypes() {
        return Collections.singleton(MyAnnotation.class.getCanonicalName());      // 注解的类 
    }

    @Override
    public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {
        System.out.print("MyProcessor process");

        MethodSpec main = MethodSpec.methodBuilder("main")
                .addModifiers(Modifier.PUBLIC, Modifier.STATIC) // 添加标识符 public static
                .returns(void.class) // 返回类型
                .addParameter(String[].class, "args") // 方法的参数
                .addStatement("$T.out.println($S)", System.class, "Hello World!")  // 方法里面的语句声明
                .build();

        // 构建 HelloWorld 类
        TypeSpec hellWorld = TypeSpec.classBuilder("HelloWorld")
                .addModifiers(Modifier.PUBLIC, Modifier.FINAL)
                .addMethod(main)
                .build();

        // 生成 java 文件
        JavaFile javaFile = JavaFile.builder(PACK_NAME, hellWorld).build();
        try {
            javaFile.writeTo(mFiler);
        } catch (Exception e){
            e.printStackTrace();

        }

        return true;
    }
}

相关的信息,可以看上面代码的注释

  • 主要是添加 auto 的注解
    @AutoService(Processor.class)
  • 版本号
    public SourceVersion getSupportedSourceVersion() {
        return SourceVersion.latestSupported();  
    }
  • 注解的类型
     public Set<String> getSupportedAnnotationTypes() {
        return Collections.singleton(MyAnnotation.class.getCanonicalName());      // 注解的类 
    }

在 process 方法中使用 JavaPoet 中的方法,生成一个输出 Hello world 的代码,这是一个官方的实例代码,关于 JavaPoet 的使用,可以去 JavaPoet github 主页 去查询。

3. 项目中对注解的使用

在项目中对上面两个 java library 引用

    dependencies {
        implementation fileTree(dir: 'libs', include: ['*.jar'])

        annotationProcessor project(':javapoetlib')
        implementation project(':annotationlib')

         ...

    }

在 activity 中使用 annoation 注解

    public class MainActivity extends AppCompatActivity {

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
        }

        @MyAnnotation(action = 2)
        public void test(){

        }

    }

现在所有的准备工作都做好,我们选择 Make Project 即可,然后我们在 app/build/generated/source/apt/debug 目录下看到生成的 hello world 文件了
这里写图片描述

发布了58 篇原创文章 · 获赞 20 · 访问量 9万+

猜你喜欢

转载自blog.csdn.net/yxhuang2008/article/details/82584500