Android 学习使用annotationprocessor自动生成java文件

来源:互联网 发布:淘宝达人登录网址 编辑:程序博客网 时间:2024/06/07 20:25

最近看glide源码,发现里面有个类必须用到的,没在源码里面,居然在build/generated目录下,这里面是自动生成的Java文件,比如R文件。

奇了个怪了,通过查阅大神文章知道了原来是利用了annotationprocessor编译器,在编译期间创建的,用到这个的出名框架比如:Butter KnifeGlide  。


注意:android-apt这个插件官方已经宣布不再维护,插件gradle2.2以上的版本使用annotationprocessor,所以我们这里跟着官方走。


否则报错:




现在我们来生成一个超级简单的Java文件吧


首先创建一个安卓项目如图:





主工程build.gradle文件如下


apply plugin: 'com.android.application'android {    compileSdkVersion 26    defaultConfig {        applicationId "com.example.alex.annotationprocessordemo"        minSdkVersion 15        targetSdkVersion 26        versionCode 1        versionName "1.0"    }    buildTypes {        release {            minifyEnabled false            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'        }    }}dependencies {    implementation fileTree(dir: 'libs', include: ['*.jar'])    implementation 'com.android.support:appcompat-v7:26.1.0'    implementation 'com.android.support.constraint:constraint-layout:1.0.2'    annotationProcessor project(':Compiler')}

接下来创建一个Java Library  Module




取好Module名字后如下图:




这里要注意,Module类型是Java Library,不要选成Android Library


编辑build.gradle后的样子如下:


apply plugin: 'java-library'dependencies {    implementation fileTree(dir: 'libs', include: ['*.jar'])    // 用于生成Java文件的库    compile 'com.squareup:javapoet:1.7.0'    compile 'com.google.auto.service:auto-service:1.0-rc2'}sourceCompatibility = "1.7"targetCompatibility = "1.7"

上面2个库一定要的,记得加上

接下来在Compiler这个module中创建一个类MyProcessor.java


package com.example.alex.compiler;import com.google.auto.service.AutoService;import com.squareup.javapoet.JavaFile;import com.squareup.javapoet.TypeSpec;import java.io.IOException;import java.util.LinkedHashSet;import java.util.Set;import javax.annotation.processing.AbstractProcessor;import javax.annotation.processing.Filer;import javax.annotation.processing.Messager;import javax.annotation.processing.ProcessingEnvironment;import javax.annotation.processing.Processor;import javax.annotation.processing.RoundEnvironment;import javax.lang.model.element.Modifier;import javax.lang.model.element.TypeElement;import javax.lang.model.util.Elements;/** * @AutoService(Processor.class) * 这个注解不要忘了,否则无法生成Java文件 */@AutoService(Processor.class)public class MyProcessor extends AbstractProcessor{    /**     * 文件相关的辅助类     */    private Filer mFiler;    /**     * 元素相关的辅助类     */    private Elements mElementUtils;    /**     * 日志相关的辅助类     */    private Messager mMessager;    /**     * 每一个注解处理器类都必须有一个空的构造函数。     * 然而,这里有一个特殊的init()方法,它会被注解处理工具调用,     * 并输入ProcessingEnviroment参数。     *     * @param processingEnvironment     */    @Override    public synchronized void init(ProcessingEnvironment processingEnvironment) {        super.init(processingEnvironment);        mElementUtils = processingEnv.getElementUtils();        mMessager = processingEnv.getMessager();        mFiler = processingEnv.getFiler();    }    @Override    public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {        // 类名和包名        TypeSpec finderClass = TypeSpec.classBuilder("MyGeneratedClass")                .addModifiers(Modifier.PUBLIC)//                .addSuperinterface(ParameterizedTypeName.get(TypeUtil.INJECTOR, TypeName.get(mClassElement.asType())))//                .addMethod(methodBuilder.build())                .build();        // 创建Java文件        JavaFile javaFile = JavaFile.builder("com.example.alex.annotationprocessordemo", finderClass).build();        try {            javaFile.writeTo(mFiler);        } catch (IOException e) {            e.printStackTrace();        }        return true;    }    /**这个方法必须重写,否则无法生成Java文件     * 这里必须指定,这个注解处理器是注册给哪个注解的。     * 注意,它的返回值是一个字符串的集合,包含本处理器想要处理的注解类型的合法全称。     * 换句话说,在这里定义你的注解处理器注册到哪些注解上。     * @return     */    @Override    public Set<String> getSupportedAnnotationTypes() {        Set<String> types = new LinkedHashSet<>();        types.add(Override.class.getCanonicalName());//        types.add(OnClick.class.getCanonicalName());        return types;    }}

重要函数解说

  • init(ProcessingEnvironment env)每一个注解处理器类都必须有一个空的构造函数。然而,这里有一个特殊的init()方法,它会被注解处理工具调用,并输入ProcessingEnviroment参数。ProcessingEnviroment提供很多有用的工具类Elements,TypesFiler

  • public boolean process(Set<? extends TypeElement> annoations, RoundEnvironment env)这相当于每个处理器的主函数main()。在这里写扫描、评估和处理注解的代码,以及生成Java文件。输入参数RoundEnviroment,可以让查询出包含特定注解的被注解元素。

  • getSupportedAnnotationTypes();这里必须指定,这个注解处理器是注册给哪个注解的。注意,它的返回值是一个字符串的集合,包含本处理器想要处理的注解类型的合法全称。换句话说,在这里定义你的注解处理器注册到哪些注解上。 

  • getSupportedSourceVersion();用来指定你使用的Java版本。

这个类就是编译期注解编译器会根据它来创建Java文件,里面提示的几个必须加上的地方要注意,忘记了就创建不了文件。


到这里基本工作都完成了,现在开始rebuild吧,成与不成就在于此了


看到了吗?主工程中build/generated/source/apt/debug目录下已经有了刚才命名的MyGeneratedClass.java 





哈哈,如果生成了说明就大功告成,没生成那么再好好找下原因是不是哪不对或者缺失了,现在又可以愉快玩耍了大笑


下面是demo链接

http://download.csdn.net/download/msn465780/10171779     点击打开链接



阅读全文
'); })();
0 0
原创粉丝点击
热门IT博客
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 华测手簿 华测检测发行价 华测点校正 华测 检测 华测检测市值 华测检测 怎么样 华测网 神舟华测 华测检测 减持 华测创时 华测检测 300012 华测gps同步软件 华测检测项目 华测检测股价 华测检测技术 华测检测 电话 华测lt30 华测检测 年报 华测检测邮箱 华测检测工资 华测郭勇 华测检测吧 华测检测 万峰 华测 股票 华测rtk测量软件 华测检测财务报表 华测检测研究院 华测检测 待遇 华测检测 董事长 华测检测 郭勇 华测检测2012年报 华测检测 股吧 华测导航 待遇 华测检测校园招聘 300012股票 检测 谱尼为什么没有华测待遇好 华浔装饰 华浔品味装饰公司口碑 华浩 华海