Android apt學習記錄

AbstractProcessor 註解處理器

javac的一個工具,用來在編譯時掃描和編譯和處理註解(Annotation)的。只能生成新文件。

  • ProcessingEnvironment

    提供 Element,Filer,Messager等工具,Filer在生成java文件使用,Messager可以打印日誌,調試時使用的最多。 (Messager日誌在Android studio - Build - Toggle View面板查看)

  • getSupportedAnnotationTypes() 指定當前處理器可以處理的註解

  • getSupportedSourceVersion() 指定java版本

  • process () 正真處理註解邏輯的地方

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

        if (set.isEmpty()) {

            mMessager.printMessage(Diagnostic.Kind.WARNING, DialogAnnotation.class.getSimpleName() + " is not used");
            return false;
        }
 
        //1、獲取註解處理器標記的所有元素
        Set<? extends Element> elementsAnnotatedWith = roundEnvironment.getElementsAnnotatedWith(DialogAnnotation.class);
        //2、遍歷元素,拿到註解值
        for (Element element : elementsAnnotatedWith) {
			//3、判斷元素類型是否是欲處理的類,element.asType()可以拿到具體類型
            if (!element.getKind().isClass()) {

                continue;
            }
			
            String clazzName = element.toString();

            //4、獲取元素上所有註解
            List<? extends AnnotationMirror> annotationMirrors = element.getAnnotationMirrors();
            for (AnnotationMirror mirror : annotationMirrors) {
 
                //獲取元素值
                Set<? extends Map.Entry<? extends ExecutableElement, ? extends AnnotationValue>> entrySet = mirror.getElementValues().entrySet();
				//5、遍歷註解上的每個鍵值對
                for (Map.Entry<? extends ExecutableElement, ? extends AnnotationValue> entry : entrySet) {
					//鍵
                    Name key = entry.getKey().getSimpleName();
					//值
                    String value = entry.getValue().toString();
                     ...處理過程...
                }

     			//打印日誌
                mMessager.printMessage(Diagnostic.Kind.NOTE, "日誌信息");
            }
        }
		
		//6、根據處理過程中的到的數據生成java文件
        createJavaFile(xxx);
        return true;

    }

JavaPoet

一個用來生成java文件的第三方庫

MethodSpec

代表一個構造函數或方法聲明
TypeSpec

代表一個類,接口,或者枚舉聲明

FieldSpec

代表一個成員變量,一個字段聲明

JavaFile

包含一個頂級類的Java文件

ParameterSpec
用來創建參數

AnnotationSpec
用來創建註解

ClassName
表示一個類,如Activity類爲:
ClassName activityClassName = ClassName.get("android.app", "Activity");

TypeName
表示類型

佔位符

$L 字面量 用於拼接字符串,不會添加""
$S 字符串 會在值前後加""
$T 類、接口
$N 變量

github例子

package com.example.helloworld;

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

// And this is the (exciting) code to generate it with JavaPoet:

MethodSpec main = 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();

TypeSpec helloWorld = TypeSpec.classBuilder("HelloWorld") //定義一個類,名爲HelloWorld
    .addModifiers(Modifier.PUBLIC, Modifier.FINAL)
    .addMethod(main)   //添加方法,可以調用多次
    .build();

JavaFile javaFile = JavaFile.builder("com.example.helloworld", helloWorld)
    .build(); //指定包名,生成java文件

javaFile.writeTo(System.out);
發佈了45 篇原創文章 · 獲贊 25 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章