概述
很多的Android或者java的框架都使用动态生成代码的技术。例如Android的ARouter,Butterknife等。今天我们简单实现是通过AbstractProcessor生成java文件。
实现
1.创建一个Android工程,工程结构如下:
image.png2.build.gradle的内容如下:
apply plugin: 'com.android.application'
android {
compileSdkVersion 26
buildToolsVersion "26.0.3"
defaultConfig {
applicationId "com.stormful.android.abstractprocessordemo"
minSdkVersion 15
targetSdkVersion 26
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:26.1.0'
//引入AbstractProcessor工程
annotationProcessor project(':compiler')
}
3.创建compiler依赖库,这个库的作用就是生成java代码。
image.png4.编写CompilerProcessor的代码,代码有注释,我就不再重复描述。
/**
* 使用AbstractProcessor生成代码
*/
@AutoService(Processor.class)
public class CompilerProcessor extends AbstractProcessor {
//文件相关的辅助类
private Filer mFiler;
//元素相关的辅助类
private Elements mElementUtils;
//日志相关的辅助类
private Messager mMessager;
@Override
public synchronized void init(ProcessingEnvironment processingEnvironment) {
super.init(processingEnvironment);
mInit();
}
/**
* 初始化常用对象
*/
private void mInit() {
mElementUtils = processingEnv.getElementUtils();
mMessager = processingEnv.getMessager();
mFiler = processingEnv.getFiler();
printLog("AbstractProcessor:" + "mInit");
}
@Override
public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {
printLog("AbstractProcessor:" + "process");
//生成一个空的类
generateEmptyClass();
//生成一个有方法的类
generateMehthodClass();
return true;
}
/**
* 这里必须指定,这个注解处理器是注册给哪个注解的。改方法不执行可能导致process方法不会执行
* 注意,它的返回值是一个字符串的集合,包含本处理器想要处理的注解类型的合法全称。
* 换句话说,在这里定义你的注解处理器注册到哪些注解上。
*
* @return
*/
@Override
public Set<String> getSupportedAnnotationTypes() {
Set<String> types = new LinkedHashSet<>();
types.add(Override.class.getCanonicalName());
return types;
}
/**
* 打印log
*
* @param msg 信息
* @param args 参数
*/
private void printLog(String msg, Object... args) {
//printLog("Generate file failed, reason: %s", "init");
mMessager.printMessage(Diagnostic.Kind.NOTE, String.format(msg, args));
}
/**
* 打印log
*
* @param msg 信息
*/
private void printLog(String msg) {
//printLog("init");
mMessager.printMessage(Diagnostic.Kind.NOTE, msg);
}
/**
* 创建一个空的java类
*/
private void generateEmptyClass() {
//创建类
TypeSpec generateEmptyClass = TypeSpec.classBuilder("GenerateEmptyClass")
.addModifiers(Modifier.PUBLIC)
.build();
//创建类存放的包名
JavaFile javaFile = JavaFile.builder("com.stormful.android.abstractprocessordemo", generateEmptyClass).build();
//创建类
try {
javaFile.writeTo(mFiler);
} catch (Exception e) {
e.printStackTrace();
}
}
private void generateMehthodClass() {
String className = "GenerateMethodClass";
String text = "我是返回值,在getTextMethod方法中";
StringBuilder builder = new StringBuilder()
.append("package com.autotestdemo.maomao.autotestdemo.auto;\n\n")
.append("public class ")
.append(className)
.append(" {\n\n") // open class
.append("\tpublic String getTextMethod() {\n") // open method
.append("\t\treturn \"");
// this is appending to the return statement
builder.append(text).append(" !");
builder.append("\";\n") // end returne
.append("\t}\n") // close method
.append("}\n"); // close class
try { // write the file
JavaFileObject source = mFiler.createSourceFile("com.stormful.android.abstractprocessordemo." + className);
Writer writer = source.openWriter();
writer.write(builder.toString());
writer.flush();
writer.close();
} catch (IOException e) {
// Note: calling e.printStackTrace() will print IO errors
// that occur from the file already existing after its first run, this is normal
e.printStackTrace();
}
}
}
5.compiler依赖的buid.gradle文件内容如下:
apply plugin: 'java-library'
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
// 用于生成Java文件的库
implementation 'com.squareup:javapoet:1.7.0'
implementation 'com.google.auto.service:auto-service:1.0-rc2'
}
//jdk版本
sourceCompatibility = "1.7"
targetCompatibility = "1.7"
效果
完成上面的代码编写之后,点击make project就能看到生成的java文件:
image.png image.png
备注
通过以上的步骤就已经可以通过AbstractProcessor一个空的类和一个带一个方法的java类了,以后还有许多知识需要学习!
我在调试这个程序的时候发现log总是看不到,之后发现是看的位置不对,网上很多帖子都是讲的是怎么用旧版本的studio查看log,但是我用的是最新的3.5.2的版本,后面通过摸索还是看到log了,下面通过截图把详细的信息也展示出来:
最后附上源码地址:https://github.com/stormdzh/AbstractProcessorDemo
欢迎大家一起学习研究!
网友评论