Android APT注解处理器自动生成文件

背景

使用(Annotation Processing Tool)即注解处理器,无论怎么Build都不能自动生成所需要的文件

添加注解

Annotation为Java library Module,很简单

1
2
3
4
5
@Target(ElementType.FIELD) //作用于属性上  
@Retention(RetentionPolicy.CLASS) //作用于编译期,.class 存在于apk中
public @interface BindView {
int value();
}
1
2
3
4
5
6
7
8
apply plugin: 'java-library'

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

sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8

添加依赖

(1)在处理注解的Java library Module 名字为Complier,添加依赖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
apply plugin: 'java-library'

dependencies {
// implementation fileTree(dir: 'libs', include: ['*.jar'])
// compiler 中用 implementation
//if (hasProperty("publishAar")) {
//implementation "cc.androidx:annotation:${VERSION_NAME}"
//} else {
implementation project(path: ':annotation')
//}

//compileOnly 'com.google.auto.service:auto-service:1.0-rc6'
implementation 'com.google.auto.service:auto-service:1.0-rc6'
annotationProcessor 'com.google.auto.service:auto-service:1.0-rc6'
implementation 'com.google.auto:auto-common:0.10'
implementation 'com.squareup:javapoet:1.11.1'
}

//中文乱码问题(错误:编码GBK不可映射字符)
tasks.withType(JavaCompile) {
options.encoding = "UTF-8"
}

sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8

(2)Java代码主要有一个类ButterKnife和一个接口ViewBinder,如下:

ButterKnife.java

1
2
3
4
5
6
7
8
9
10
11
12
public class ButterKnife {
public static void bind(Activity activity) {
String className = activity.getClass().getName() + "$ViewBinder";
try {
Class<?> aClass = Class.forName(className);
ViewBinder viewBinder = (ViewBinder) aClass.newInstance();
viewBinder.bind(activity);
} catch (Exception e) {
e.printStackTrace();
}
}
}

ViewBinder.java

1
2
3
public interface ViewBinder<T> {
void bind(T t);
}

注解处理器(Complier)

在Complier Module中,只需有一个类ButterKnifeProcessor即可实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
@AutoService(Processor.class)  //加上这个注解才能去执行
public class ButterKnifeProcessor extends AbstractProcessor {
private Elements elementUtils; //Elements中包含用于操作的工具
private Filer filer; //用来创建新的源文件,class以及其他文件

@Override
public synchronized void init(ProcessingEnvironment processingEnvironment) {
super.init(processingEnvironment);
//此方法主要是去初始化需要用到的工具
elementUtils = processingEnvironment.getElementUtils();
filer = processingEnvironment.getFiler();
}

@Override
public Set<String> getSupportedAnnotationTypes() {
//添加支持的注解类型
Set<String> setTypes = new LinkedHashSet<>();
setTypes.add(BindView.class.getCanonicalName()):
return setTypes;
}

@Override
public SourceVersion getSupportedSourceVersion() {
//用哪个版本的jdk编译
return SourceVersion.RELEASE_8;
}

/**
* 注解处理器的核心方法,处理具体的注解,生成新的 Java Class文件
*/
@Override
public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {
try {
JavaFileObject fileObject = filer.createSourceFile("LuacherActivity$ViewBinder");
//获取writer,wirter就类似一支笔,去写java文件里的每一行代码
Writer writer = fileObject.openWriter();
writer.write("package cn.appblog.apt;\n"); //包名
writer.write("\n");
writer.write("import cn.appblog.aptlib.ViewBinder;\n");//导包
writer.write("\n");
writer.write("import cn.appblog.apt.LuacherActivity;\n");
writer.write("\n");
writer.write("import cn.appblog.apt.R;\n");
writer.write("\n");
writer.write("public class LuacherActivity$ViewBinder implements ViewBinder<LuacherActivity> {\n");
writer.write(" @Override\n");
writer.write(" public void bind(LuacherActivity target) {\n");
writer.write(" target.tvText = target.findViewById(R.id.tv_text);\n}\n");
writer.write("}");
//最后不要忘记关流
writer.flush();
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
}

目前代码写死,真正实现可以从参数RoundEnvironment中获取到注解的类,这里只是看下Writer的用法。具体实现可以参考 【Android】APT

主要是重写init(ProcessingEnvironment processingEnvironment)getSupportedAnnotationTypes()getSupportedSourceVersion()以及process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment)这四个方法

寻找不能自动生成文件的问题

(1)@AutoService(Processor.class),这个注解必须添加,否则注解处理器不能执行

(2)最后写完wirter流没有关闭,会造成生成文件,但文件内容为空,或者不全

(3)app Module 要添加之前的三个Library依赖,如下:

1
2
implementation project(path: ':Annotation')
annotationProcessor project(path: ':Complier')

以上反复检查了N次,确认无误仍然不能编译生成想要看到的文件,最后找个大神请教下。说是Android Gradle及构建版本问题,我的是3.4.2 + 5.2.1,会出现不兼容的情况,大神建议3.4.2 + 5.1.1及以下都可以。听了建议降低版本果然构建编译成功,新的文件生成

自动生成的LuacherActivity$ViewBinder

1
2
3
4
5
6
7
8
9
10
11
12
package cn.appblog.apt;

import cn.appblog.aptlibViewBinder;
import cn.appblog.apt.LuacherActivity;
import cn.appblog.apt.R;

public class LuacherActivity$ViewBinder implements ViewBinder<LuacherActivity> {
@Override
public void bind(LuacherActivity target) {
target.tvText = target.findViewById(R.id.tv_text);
}
}

Powered by AppBlog.CN     浙ICP备14037229号

Copyright © 2012 - 2020 APP开发技术博客 All Rights Reserved.

访客数 : | 访问量 :