本文基于ButterKnife版本:
'com.jakewharton:butterknife:10.2.1'
'com.jakewharton:butterknife-compiler:10.2.1'
1-自定义注解处理器
java代码编译期,javac会调用java注解器来处理注解相关。先看下butterknife-compiler库中的核心ButterKnifeProcessor
通过继承AbstractProcessor实现自定义处理器,重写以下方法
public class ButterKnifeProcessor extends AbstractProcessor {
//指定java版本
@Override
public SourceVersion getSupportedSourceVersion() {
return SourceVersion.latestSupported();
}
//(1)初始化辅助类
@Override
public synchronized void init(ProcessingEnvironment env) {
super.init(env);
String sdk = env.getOptions().get(OPTION_SDK_INT);
if (sdk != null) {
try {
this.sdk = Integer.parseInt(sdk);
} catch (NumberFormatException e) {
env.getMessager()
.printMessage(Kind.WARNING, "Unable to parse supplied minSdk option '"
+ sdk
+ "'. Falling back to API 1 support.");
}
debuggable = !"false".equals(env.getOptions().get(OPTION_DEBUGGABLE));
typeUtils = env.getTypeUtils();
filer = env.getFiler();
try {
trees = Trees.instance(processingEnv);
} catch (IllegalArgumentException ignored) {
try {
// Get original ProcessingEnvironment from Gradle-wrapped one or KAPT-wrapped one.
for (Field field : processingEnv.getClass().getDeclaredFields()) {
if (field.getName().equals("delegate") || field.getName().equals("processingEnv")) {
field.setAccessible(true);
ProcessingEnvironment javacEnv = (ProcessingEnvironment) field.get(processingEnv);
trees = Trees.instance(javacEnv);
break;
}
}
} catch (Throwable ignored2) {
}
}
}
//返回目标注解集合
@Override
public Set<String> getSupportedAnnotationTypes() {
Set<String> types = new LinkedHashSet<>();
for (Class<? extends Annotation> annotation : getSupportedAnnotations()) {
types.add(annotation.getCanonicalName());
}
return types;
}
//(2)核心方法。先扫描查找注解,再生成java文件
@Override public boolean process(Set<? extends TypeElement> elements, RoundEnvironment env) {
//@1.查找注解信息,生成BindingSet并保存到bingdingMap中
Map<TypeElement, BindingSet> bindingMap = findAndParseTargets(env);
//@4.遍历bindingMap,生成对应的 className_ViewBinding.java文件
for (Map.Entry<TypeElement, BindingSet> entry : bindingMap.entrySet()) {
TypeElement typeElement = entry.getKey(