编译时注解学习三之 注解处理器AbstractProcessor工具和Element属性简述

1 如何读取build.gradle配置的常量

配置,读取:

@SupportedOptions({"CLASSNAME"})
@SupportedAnnotationTypes("com.ldx.annotationlib.BindView")
@SupportedSourceVersion(SourceVersion.RELEASE_7)
//@AutoService(Processor.class)
public class AptProcessor extends AbstractProcessor {

    private Map<String,String> mOptionMap;

    @Override
    public synchronized void init(ProcessingEnvironment processingEnvironment) {
        super.init(processingEnvironment);
        mOptionMap = processingEnv.getOptions();
    }

    @Override
    public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {
        if (set != null && set.size() > 0){

            Set<? extends Element>  elements = roundEnvironment.getElementsAnnotatedWith(BindView.class);
            for (Element element : elements) {
                VariableElement variableElement = (VariableElement) element;
                //读取配置参数
                mMessager.printMessage(Diagnostic.Kind.NOTE,"aptprocessor     "+mOptionMap.get("CLASSNAME"));

                createFile(enclosingElement, bindViewFiledClassType, bindViewFiledName, bindAnnotation.value());
            }

            return true;
        }
        return false;
    }

build.gradle中配置(如何配置编译时注解变量):

 javaCompileOptions {
            annotationProcessorOptions {
                arguments = ["xxxx":"xxxxx", "CLASSNAME":"lidxclassname"]

            }
        }

2 打印信息

由于在编译期,所以无法利用System,log,打印信息,系统提供了Messager工具进行信息的打印。
private Messager mMessager = processingEnv.getMessager();;


打印日志的几个方法

第一个参数Kind标识日志的级别,包括:

 public static enum Kind {
        ERROR,
        WARNING,
        MANDATORY_WARNING,
        NOTE,
        OTHER;

        private Kind() {
        }
    }

第二个参数为打印信息,后面参数Element为需要打印的Element。

3 Elements 工具

Elements mElementsUtils = processingEnv.getElementUtils();


方法
  //包名
mMessager.printMessage(Diagnostic.Kind.NOTE,"aptprocessor     "+mElementsUtils.getPackageOf(enclosingElement).asType().toString());
mMessager.printMessage(Diagnostic.Kind.NOTE,"aptprocessortwo     "+mElementsUtils.getBinaryName(enclosingElement));
mMessager.printMessage(Diagnostic.Kind.NOTE,"aptprocessortwo     "+mElementsUtils.getPackageOf(enclosingElement).getQualifiedName().toString());
mMessager.printMessage(Diagnostic.Kind.NOTE,"aptprocessortwo     "+mElementsUtils.isDeprecated(enclosingElement));
mMessager.printMessage(Diagnostic.Kind.NOTE,"aptprocessortwo     "+mElementsUtils.getPackageElement("com.ldx.canvasdrawdemo").getQualifiedName());

4 Filer,生成文件的工具类

Filer mFilerUtils = processingEnv.getFiler();
完全类名:javax.annotation.processing.Filer,注解处理器可用此创建新文件(源文件、类文件、辅助资源文件)。由此方法创建的源文件和类文件将由管理它们的工具(javac)处理


介绍
生成文件方法

apt常用方法为:


参数解释
  • 第一个参数为生成的java文件的全限定名(也就是包名和文件名,写法应该是包名(com.ldx.xx)然后加上一个点(.)在加上文件名),例如要生成com.ldx.xx.demo.java,第一个参数写法为"com.ldx.xx.demo",其中demo就是文件名。
  • 第二个参数是与此文件的创建有因果关联的类型或包元素,该参数可以省略或者为 null,类型为一个数组,一般写法为new Element[]{}或者为null。
//例子
  private void createFile(TypeElement enclosingElement, String bindViewFiledClassType, String bindViewFiledName, int id) {
        String pkName = mElementsUtils.getPackageOf(enclosingElement).getQualifiedName().toString();
        String packName = mElementsUtils.getPackageOf(enclosingElement).asType().toString();
        String className = enclosingElement.getSimpleName().toString();
        try {
            JavaFileObject jfo = mFilerUtils.createSourceFile(pkName + "."+className+ "$ViewBinding", new Element[]{});
            Writer writer = jfo.openWriter();
            writer.write(brewCode(className,pkName, bindViewFiledClassType, bindViewFiledName, id));
            writer.flush();
            writer.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private String brewCode(String className,String pkName, String bindViewFiledClassType, String bindViewFiledName, int id) {
        StringBuilder builder = new StringBuilder();
        builder.append("package " + pkName + ";\n\n");
        builder.append("public class " + className + "$ViewBinding { \n\n");
        builder.append("public static void main(String[] args){ \n\n");
        String info = String.format("%s %s = findViewById(%d)", bindViewFiledClassType, bindViewFiledName, id);
        builder.append("System.out.println(\"" + info + "\");\n\n");
        builder.append("}\n\n");
        builder.append("}");
        return builder.toString();
    }

5 ElementKind

如何判断Element的类型呢,需要用到ElementKind,ElementKind为元素的类型,元素的类型判断不需要用instanceof去判断,而应该通过getKind()去判断对应的类型
类型 说明
PACKAGE 包
ENUM 枚举
CLASS 类
ANNOTATION_TYPE 注解
INTERFACE 接口
ENUM_CONSTANT 枚举常量
FIELD 字段
PARAMETER 方法参数
LOCAL_VARIABLE 局部变量
METHOD 方法
CONSTRUCTOR 构造方法
TYPE_PARAMETER 类型参数

  Set<? extends Element>  elements = roundEnvironment.getElementsAnnotatedWith(BindView.class);
            for (Element element : elements) {
                ElementKind kind = element.getKind();
                if (kind.isField()){
                   mMessager.printMessage(Diagnostic.Kind.NOTE,"aptprocessor     "+"element 是 Field,利用VariableElement进行强转");
                }
                }

6 TypeMirror

TypeMirror是一个接口,表示Java编程语言中的类型。这些类型包括基本类型、引用类型、数组类型、类型变量和null类型等等

类型 说明
ArrayType 表示数组类型
DeclaredType 表示声明类型(类或接口类型)
ErrorType 表示异常类或接口类型
ExecutableType 表示executable类型(方法、构造方法、初始化)
NoType 表示在实际类型不适合的地方使用的伪类型
NullType 表示null类型
PrimitiveType 表示基本数据类型
ReferenceType 表示引用类型
TypeVariable 表示类型变量
WildcardType 表示通配符类型参数

 for (Element element : elements) {
                ElementKind kind = element.getKind();
                if (kind.isField()){
                    mMessager.printMessage(Diagnostic.Kind.NOTE,"aptprocessor     "+"element 是 Field,利用VariableElement进行强转");
                    TypeMirror mirror = element.asType();
                    
                    TypeKind kind1 = mirror.getKind();
                    
                }

如果Element是一个VariableElement,variableElement.asType().toString()可以获取它的全类名。

  String bindViewFiledClassType = variableElement.asType().toString();
                //变量名
                mMessager.printMessage(Diagnostic.Kind.NOTE,"aptprocessor     "+bindViewFiledClassType);

输出:
android.widget.TextView

7 TypeKind

TypeKind为类型的属性,类型的属性判断不需要用instanceof去判断,而应该通过getKind()去判断对应的属性

类型 说明
BOOLEAN 基本类型boolean
INT 基本类型int
LONG 基本类型long
FLOAT 基本类型float
DOUBLE 基本类型double
VOID 对应于关键字void的伪类型
NULL null类型
ARRAY 数组类型
PACKAGE 对应于包元素的伪类型
EXECUTABLE 方法、构造方法、初始化
DECLARE 声明类型

 for (Element element : elements) {
                ElementKind kind = element.getKind();
                if (kind.isField()){
                    mMessager.printMessage(Diagnostic.Kind.NOTE,"aptprocessor     "+"element 是 Field,利用VariableElement进行强转");
                    TypeMirror mirror = element.asType();
                    
                    TypeKind kind1 = mirror.getKind();
                    
                }

8 Types

Types mTypesUtils = processingEnv.getTypeUtils();
Type操作工具,包括对TypeMirror,TypeKind,DeclaredType


方法1
方法2

asElement,根据特定TypeMirror获取与之关联的ElementType。
contains,是否一个TypeMirror包含另外一个TypeMirror,类似数组和普通元素。
。。。。。。。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,607评论 6 507
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,239评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,960评论 0 355
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,750评论 1 294
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,764评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,604评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,347评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,253评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,702评论 1 315
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,893评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,015评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,734评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,352评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,934评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,052评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,216评论 3 371
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,969评论 2 355