Android 基础系列(3)编译时注解处理器 APT,android 订餐系统源码
定义注解
定义注解处理器(AbstractProcess)
处理器中生成 java 代码(可以采用 javaPoet)
注册处理器(AutoService)
创建 apt-annotation 模块
定义
BindView
注解
@Retention(RetentionPolicy.CLASS) // 编译时注解 @Target(ElementType.FIELD) // 注解范围为类成员 public @interface BindView {int value();}
创建 apt-processor 模块
定义注解处理器,生成需要的代码,注册处理器
// BindViewProcessor.java@AutoService(Processor.class) // 注册处理器 public class BindViewProcessor extends AbstractProcessor {
private Elements mElementUtils;private Map<String, ClassCreatorProxy> mProxyMap = new HashMap<>();
// ProcessingEnvironment 提供很多有用的工具类 Elements, Types 和 Filer@Overridepublic synchronized void init(ProcessingEnvironment processingEnv) {super.init(processingEnv);mElementUtils = processingEnv.getElementUtils();}
/**
指定这个注解处理器是注册给哪个注解的,这里是 BindView*/@Overridepublic Set<String> getSupportedAnnotationTypes() {HashSet<String> supportTypes = new LinkedHashSet<>();supportTypes.add(BindView.class.getCanonicalName());return supportTypes;}
/**
指定使用的 Java 版本,通常这里返回 SourceVersion.latestSupported()*/@Overridepublic SourceVersion getSupportedSourceVersion() {return SourceVersion.latestSupported();}
@Overridepublic boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {//根据注解生成 Java 文件 mProxyMap.clear();//得到所有的注解 Set<? extends Element> elements = roundEnvironment.getElementsAnnotatedWith(BindView.class);for (Element element : elements) {VariableElement variableElement = (VariableElement) element;TypeElement classElement = (TypeElement) variableElement.getEnclosingElement();String fullClassName = classElement.getQualifiedName().toString();ClassCreatorProxy proxy = mProxyMap.get(fullClassName);if (proxy == null) {proxy = new ClassCreatorProxy(mElementUtils, classElement);mProxyMap.put(fullClassName, proxy);}BindView bindAnnotation = variableElement.getAnnotation(BindView.class);int id = bindAnnotation.value();proxy.putElement(id, variableElement);}for (String key : mProxyMap.keySet()) {ClassCreatorProxy proxyInfo = mProxyMap.get(key);JavaFile javaFile = JavaFile.buil
der(proxyInfo.getPackageName(), proxyInfo.generateJavaCode()).build();try {// 生成文件 javaFile.writeTo(processingEnv.getFiler());} catch (IOException e) {e.printStackTrace();}}
return true;}}
// ClassCreatorProxy.java// JavaPoet 生成 java 代码 public class ClassCreatorProxy {private String mBindingClassName;private String mPackageName;private TypeElement mTypeElement;private Map<Integer, VariableElement> mVariableElementMap = new HashMap<>();
public ClassCreatorProxy(Elements elementUtils, TypeElement classElement) {this.mTypeElement = classElement;PackageElement packageElement = elementUtils.getPackageOf(mTypeElement);String packageName = packageElement.getQualifiedName().toString();String className = mTypeElement.getSimpleName().toString();this.mPackageName = packageName;this.mBindingClassName = className + "_ViewBinding";}
public void putElement(int id, VariableElement element) {mVariableElementMap.put(id, element);}
/**
创建 Java 代码*/public TypeSpec generateJavaCode() {return TypeSpec.classBuilder(mBindingClassName).addModifiers(Modifier.PUBLIC).addMethod(generateMethods()).build();
}
评论