官方文档:Getting Started with the Annotation PRocessing Tool (apt)
如果想学习APT,那么就必须先了解Annotation的基础,这里附加我另外一篇文章的地址: Annotation - QQ_20198405的博客 - 博客频道 - CSDN.NET
APT(Annotation Processing Tool)是一种处理注解的工具,它对源代码文件进行检测找出其中的Annotation,使用Annotation进行额外的处理。 Annotation处理器在处理Annotation时可以根据源文件中的Annotation生成额外的源文件和其它的文件(文件具体内容由Annotation处理器的编写者决定),APT还会编译生成的源文件和原来的源文件,将它们一起生成class文件。
新建一个名称为annotation的java Library,主要放置一些项目中需要使用到的Annotation和关联代码。 这里简单自定义了一个注解:
@Target(ElementType.TYPE)@Retention(RetentionPolicy.CLASS)public @interface AptAnnotation {}新建一个名为compiler的Java Library,这个类将会写代码生成的相关代码。核心就是在这里。
tasks.withType
是设置编码格式,避免AptProcesser 中的中文注释报错依赖上面创建的annotation Module。生成代码相关的逻辑就放在这里。
@AutoService(Processor.class) public class AptProcesser extends AbstractProcessor { @Override public Set<String> getSupportedAnnotationTypes() { return Collections.singleton(AptAnnotation.class.getCanonicalName()); } @Override public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { return false; } }我们接下来要生成下面这个HelloWorld的代码:
package com.example.helloworld; public final class HelloWorld { public static void main(String[] args) { System.out.println("Hello, JavaPoet!"); } }修改上述AptProcesser 的process方法
@Override public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) { MethodSpec main = MethodSpec.methodBuilder("main") .addModifiers(Modifier.PUBLIC, Modifier.STATIC) .returns(void.class) .addParameter(String[].class, "args") .addStatement("$T.out.println($S)", System.class, "Hello, JavaPoet!") .build(); TypeSpec helloWorld = TypeSpec.classBuilder("HelloWorld") .addModifiers(Modifier.PUBLIC, Modifier.FINAL) .addMethod(main) .build(); JavaFile javaFile = JavaFile.builder("com.example.helloworld", helloWorld) .build(); try { javaFile.writeTo(processingEnv.getFiler()); } catch (IOException e) { e.printStackTrace(); } return false; }点击Android Studio的ReBuild Project,可以在在app的 build/generated/source/apt/debug 目录下,即可看到生成的代码。
到目前我们还没有使用注解,上面的@AptAnnotation 也没有实际用上,下面我们做一些更加实际的代码生成。实现基于注解的View,代替项目中的findByView 。这里仅仅是学习怎么用APT,如果真的想用DI框架,推荐使用ButterKnife,功能全面。
实际上就是通过apt生成以下代码:
public final class DIMainActivity { public static void bindView(MainActivity activity) { activity.textView1 = (android.widget.TextView) activity.findViewById(2131427413); activity.textView2 = (android.widget.TextView) activity.findViewById(2131427414); activity.textView3 = (android.widget.TextView) activity.findViewById(2131427415); }}常用Element子类
TypeElement:类ExecutableElement:成员方法VariableElement:成员变量
通过包名和类名获取TypeName
TypeName targetClassName = ClassName.get("PackageName", "ClassName");通过Element获取TypeNameTypeName type = TypeName.get(element.asType());获取TypeElement的包名String packageName = processingEnv.getElementUtils().getPackageOf(type).getQualifiedName().toString();获取TypeElement的所有成员变量和成员方法List<? extends Element> members = processingEnv.getElementUtils().getAllMembers(typeElement);总结:
推荐阅读dagger2、dbflow、ButterKnife等基于apt的开源项目代码。JavaPoet 也有很多例子可以学习。
源码传送 参考: Android APT(编译时代码生成)最佳实践 - 推酷 例子: 代码传送(稍加注释) Android 利用 APT 技术在编译期生成代码 - hb707934728的博客 - 博客频道 - CSDN.NET
相关文章: android-apt 翻译 - 简书 原文hvisser / android-apt — Bitbucket Annotation-Processing-Tool详解 | qiushao http://qiushao.net/2015/07/07/Annotation-Processing-Tool%E8%AF%A6%E8%A7%A3/ AndroidSutdio 编译时自动生成源代码 | Septenary http://www.septenary.cn/2015/12/19/AndroidSutdio-%E7%BC%96%E8%AF%91%E6%97%B6%E8%87%AA%E5%8A%A8%E7%94%9F%E6%88%90%E6%BA%90%E4%BB%A3%E7%A0%81/
Android 打造编译时注解解析框架 这只是一个开始 - Hongyang - 博客频道 - CSDN.NET http://blog.csdn.net/lmj623565791/article/details/43452969 Android 如何编写基于编译时注解的项目 - Hongyang - 博客频道 - CSDN.NET http://blog.csdn.net/lmj623565791/article/details/51931859
bug解决: Android Studio出现Error:No service of type Factor… - 简书 http://www.jianshu.com/p/c4f4894ad215 Android Studio Error—Gradle: 错误:编码 GBK 的不可映射字符的 - 黑暗领域 - 博客频道 - CSDN.NET http://blog.csdn.net/sljjyy/article/details/11976099
新闻热点
疑难解答