什么是APT?
编译时注解,就是在编译期间对源文件检查,并找出指定的注解,然后根据注解生成新的源文件,最终和原来的源文件共同被编译成class文件,具体流程如下(图摘抄自Android 注解系列之APT工具(三)):
自己的例子
使用
- gradle中引用
dependencies {
...
implementation project(":BindEvent")
annotationProcessor project(":annotation_compiler")
}
- Activity中的使用
public class MainActivity extends AppCompatActivity {
@BindView(R.id.tv_test)
TextView tvTest;
@BindView(R.id.btn_main)
Button btnMain;
@BindView(R.id.btn1_main)
Button btn1Main;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
BindEvent.bind(this);
}
}
效果
make项目就会自动生成对应代码,如下图:
开发步骤
1.新建一个名为annotation的Java的library库,并新建一个注解,如下:
2.新建一个名为compiler的Java的library库,并在build.gradle中添加一下代码
dependencies {
...
implementation project(":annotation")
compileOnly "com.google.auto.service:auto-service:1.0-rc6"
annotationProcessor "com.google.auto.service:auto-service:1.0-rc6"
implementation "com.squareup:javapoet:1.10.0"
}
3.在compiler的库中新建一个类并继承AbstractProcessor,并实现其方法,主要代码如下
/**
* 注解处理器 解析指定注解并生成Java 代码
*/
//@AutoService(Processor.class)
public class AnnotationProcessor extends AbstractProcessor {
/**
* @param set
* @param roundEnvironment 携带了项目中 所有这个注解处理器声明了的 注解 所标注的 内容
* @return
*/
@Override
public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {
// process 方法会执行多次
// 但是 set里面有数据的只会执行一次
if (set.iterator().hasNext()) {
// 拿到所有的BindView 并且根据上层节点分开的map
Map<TypeElement, List<Element>> map = ParseTargets(roundEnvironment);
// 根据map里的数据分别生成 Java文件
if (map.size() > 0) {
for (TypeElement typeElement : map.keySet()) {
// 创造 方法(构造是方法的一种)
MethodSpec.Builder builder = MethodSpec.constructorBuilder();
// 添加参数
// builder.addParameter(TypeVariableName.get(packageName + "." + activityName), "target");
builder.addParameter(TypeVariableName.get(typeElement.getQualifiedName().toString()), "target");
builder.addParameter(ClassName.get("android.view", "View"), "view");
for (Element e : map.get(typeElement)) {
String fieldName = e.getSimpleName().toString();
int id = e.getAnnotation(BindView.class).value();
// 设置数据
builder.addStatement("target.$L = view.findViewById($L)", fieldName, id);
}
MethodSpec methodSpec = builder.build();
String newName = typeElement.getSimpleName() + "_ViewBind";
//获取包名
String packageName = getPackageName(typeElement);
// 创建类
TypeSpec typeSpec = TypeSpec.classBuilder(newName)
.addModifiers(Modifier.PUBLIC)
.addMethod(methodSpec)
.build();
JavaFile javaFile = JavaFile.builder(packageName, typeSpec).build();
try {
javaFile.writeTo(filer);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
return false;
}
}
4.注册注解处理器(这里有两种方法)
参考文献
- Android 注解系列之APT工具(三)
|