win10如何进入debugdebug自定义AbstractProcessor

android 中运用apt自定义一个AbstractProcessor // Yzx Blog
apt 全称 Annotation Processing Tool,基础的知识参见后面这个链接 运用apt,可以减少代码增加代码可读性又比反射的效率高。
我使用的方法是在intellj中建一个基于maven的java project,编译成jar包,然后放到androidstudio中。首先在intellj中new一个java项目,定一个注解,下面定义的这个注解是用来修饰方法并且在编译时处理的。
123456789@Retention(CLASS)@Target(METHOD)public @interface WRMPOST
String className();
String value() default "Hello";
int type() default 0;}
然后继承自AbstractProcessor定义一个处理注解的类,这里我生成了一个文件,类似于butterknife就是用这种方式生成了一个文件,用来帮助activity或者其他findviewbyid的, dagger也是如此。
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162@SupportedSourceVersion(SourceVersion.RELEASE_7)public class MyProcessor extends AbstractProcessor {
public static final String SUFFIX = "$$WrmRequestInfo";
public synchronized void init(ProcessingEnvironment env) {
super.init(env);
public Set&String& getSupportedAnnotationTypes() {
Set&String& types = new LinkedHashSet&String&();
types.add(WRMPOST.class.getCanonicalName());
public boolean process(Set&? extends TypeElement& annotations, RoundEnvironment env) {
for (Element e : env.getElementsAnnotatedWith(WRMPOST.class)) {
WRMPOST ca = e.getAnnotation(WRMPOST.class);
String name = e.getSimpleName().toString();
char[] c = name.toCharArray();
c[0] = Character.toUpperCase(c[0]);
name = new String(name);
TypeElement clazz = (TypeElement) e.getEnclosingElement();
JavaFileObject f = processingEnv.getFiler().createSourceFile(clazz.getQualifiedName() + SUFFIX);
processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, "Creating " + f.toUri());
Writer w = f.openWriter();
String pack = clazz.getQualifiedName().toString();
PrintWriter pw = new PrintWriter(w);
pw.println("package " + pack.substring(0, pack.lastIndexOf('.')) + ";");
pw.println("\npublic class " + clazz.getSimpleName() + "Autogenerate {");
pw.println("\n
public " + ca.className() + " result = \"" + ca.value() + "\";");
pw.println("
public int type = " + ca.type() + ";");
pw.println("\n
protected " + clazz.getSimpleName() + "Autogenerate() {}");
pw.println("\n
/** Handle something. */");
pw.println("
protected final void handle" + name + "(" + ca.className() + " value" + ") {");
pw.println("\n//" + e);
pw.println("//" + ca);
pw.println("\n
System.out.println(value);");
pw.println("
pw.println("}");
pw.flush();
} finally {
w.close();
} catch (IOException x) {
processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR,
x.toString());
return true;
public SourceVersion getSupportedSourceVersion() {
return SourceVersion.latestSupported();
在resources目录中建一个javax.annotation.processing.Processor文件,然后填写自定义processor的路径,这个项目中写的是piler.internal.MyProcessor
在pom.xml添加编译插件
12345678910111213141516171819202122232425&?xml version="1.0" encoding="UTF-8"?& xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"&
&compiler&
&1.0-SNAPSHOT&
&org.apache.maven.plugins&
&maven-compiler-plugin&
&-proc:none&
配置intellj生成一个jar包,在File -& Project Structure -& Artifacts -& Add -& Jar -& From modules with dependencies.. -& ok -& 选上Build on make -& Ok。这样就可以Build出一个jar包了。然后把jar包添加到androidstudio中的libs,在build.gradle compile file (‘libs/xxx.jar’) 就可以了。将我们之前定义的注解使用到一个方法中,rebuild之后, 就可以在app/build/intermediates/classes/中对应使用注解的文件目录下生成一个我们自己创建的.java文件和其编译后的.class文件。
大功告成!
Keep Writing
This post does not have a Table Of Contents
Powered byorg.gradle.jvmargs-学网-提供健康,养生,留学,移民,创业,汽车等信息
org.gradle.jvmargs
& com.mon.process.ProcessException: org.gradle.process.internal.ExecException: Process 'command 'D:\adt-bundle-windows-x86_64-\sdk... 错误:java.lang.UnsupportedClassVersionError: Bad version number in .class file 造成这种错误的原因是你的支持Tomcat运行的JDK版本与支持application运行的JDK版本不一...org.gradle.daemon=true org.gradle.jvmargs=-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005 在命令行中运行gradle daemon来启动守护线程。 gradle --d...useful&for&tweaking&memory&settings. #&Default&value:&-Xmx10248m&-XX:MaxPermSize=256m org.gradle.jvmargs=-Xmx2048m...1首先官网gradle.org载新gradle版本 2载完放任意位置我D:/gradle-1.1需要放换进配置步骤右键计算机-属性进入高级配置选择环境变量点击新建配置GRADLE_HOME 3选择pa...在C盘\用户\你的用户名\.gradle目录下新建一个文件名为gradle.properties的文件。 内容为: org.gradle.daemon=true 看看能不能解决,求采纳中搜索 Gradle, 选择安装 Gradle Integration for Eclipse 2.新建一个 Dynamic Web Project, 在项目根目录下新建 build.gradle 文件, 并向其中写入如下内容: import org.gradle.plu...1,首先当然是到官网gradle.org下载最新的gradle版本了 2,下载完成后,放到任意的位置,我的是在D:/gradle-1.1,然后需要放到换进配置,步骤是右键"计算机"-"属性",进入"高级配置...gradle在,android studio的配置中看,如果不是,在项目的gradle/wrapper目录下面有个gradle-wrapper.properties中有如下内容: distributionUrl=https\://services.gradle.org/distribut...Web Project, 在项目根目录下新建 build.gradle 文件, 并向其中写入如下内容:930import&org.gradle.plugins.id...
您可能还关注:&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
大类导航: |Android学习(366)
Java实现基于LRU的磁盘缓存
一个强大的加载,缓存,展示图片的库
一个强大的图片下载与缓存的库
一个用于管理图像和他们使用的内存的库
一个图片加载和缓存的库
一个为Picasso提供多种图片变换的库
一个为Glide提供多种图片变换的库
基于OpenGL的Android过滤器
Android异步HTTP库
异步Socket,HTTP(客户端+服务器),WebSocket,和socket.io库。基于NIO而不是线程。
一个Http与Http/2的客户端
类型安全的Http客户端
Google推出的Android异步网络请求框架和图片加载框架
一个Java序列化/反序列化库,可以将JSON和java对象互相转换
Jackson可以轻松地将Java对象转换成json对象和xml文档,同样也可以将json、xml转换成Java对象
Java上一个快速的JSON解析器/生成器
一种用来解析单个独立html或嵌套html的方式
一个以最好的DOM,CSS和jQuery解析html的库
JDBC和Android的轻量级ORM java包
用超级简单的方法处理Android数据库
一种轻快地将对象映射到SQLite数据库的ORM解决方案
以活动记录方式为Android SQLite提供持久化
SQLiteOpenHelper 和ContentResolver的轻量级包装
移动数据库:一个SQLite和ORM的替换品
将Android视图和回调方法绑定到字段和方法上
一个Android和java快速依赖注射器。
快速安卓开发。易于维护
Android平台的Google Guice
创建图表的Android库
兼容到API8的Android图表库
一个强大的Android图表视图/图形库
一个轻快的,事务性的,基于文件的FIFO的库
一个专门为Android轻松调度任务的工作队列
安卓优化的事件总线,简化了活动、片段、线程、服务等的通信
一个基于Guava的增强的事件总线
JVM上的响应式扩展
为RxJava提供Joins操作
Android上的响应式扩展,在RxJava基础上添加了Android线程调度
提供用RxJava绑定Android UI的API
Android上的响应式编程
简单,漂亮,强大的Android日志工具
在调试版本上注解的触发方法进行日志记录
一个小的,可扩展的日志工具
Java编写的Mocking单元测试框架
Android UI 测试
Android单元测试框架
Android自带很多测试工具:JUnit,Monkeyrunner,UiAutomator,Espresso等
调试Android应用的桥梁,使得可以利用Chrome开发者工具进行调试
内存泄漏检测工具
Android应用程序崩溃报告
文章链接:
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:304182次
积分:6481
积分:6481
排名:第2900名
原创:279篇
转载:596篇
评论:40条
(1)(24)(7)(15)(7)(27)(8)(8)(15)(18)(60)(60)(12)(24)(45)(11)(20)(49)(35)(12)(38)(57)(46)(21)(61)(89)(81)(23)(8)介绍了JavaPoet的原理和使用,这里在介绍一下的原理,并模仿自定义实现一个AutoValue。
AutoValue的是Google为了实现ValueClass设计的自动编译框架,具体的介绍可以参考Google的官方。
Dagger内部也大量使用了AutoValue的功能,来实现ValueClass。
AutoValue嵌入到JavaClass的编译过程,读取被注解的类,来创建一个新的ValueClass。这里有一个完整使用的。
这里主要介绍一下AutoValue的实现。
定义注解AutoValue。
@Retention(RetentionPolicy.SOURCE)
@Target(ElementType.TYPE)
public @interface AutoValue {
注册processor,AutoValue的jar包中的META-INF/services路径里面包含文件javax.annotation.processing.Processor,文件里包含了注册的processor,换行分割。这里面注册了AutoValueProcessor。
AutoValueProcessor的process方法实现了主要的处理逻辑,读取注释的类的信息,构造新的类,并写入文件。processType方法是处理单个类的方法,主要的逻辑如下
AutoValueTemplateVars vars = new AutoValueTemplateVars();
vars.pkg = TypeSimplifier.packageNameOf(type);
vars.origClass = TypeSimplifier.classNameOf(type);
vars.simpleClassName = TypeSimplifier.simpleNameOf(vars.origClass);
vars.subclass = TypeSimplifier.simpleNameOf(subclass);
vars.finalSubclass = TypeSimplifier.simpleNameOf(finalSubclass);
vars.isFinal = applicableExtensions.isEmpty();
vars.types = processingEnv.getTypeUtils();
determineObjectMethodsToGenerate(methods, vars);
defineVarsForType(type, vars, toBuilderMethods, propertyMethods, builder);
GwtCompatibility gwtCompatibility = new GwtCompatibility(type);
vars.gwtCompatibleAnnotation = gwtCompatibility.gwtCompatibleAnnotationString();
String text = vars.toText();
text = Reformatter.fixup(text);
writeSourceFile(subclass, text, type);
AutoValueTemplateVars保存了新的类的信息,并根据对应的模板生成源文件字符串.
private void writeSourceFile(String className, String text, TypeElement originatingType) {
JavaFileObject sourceFile =
processingEnv.getFiler().createSourceFile(className, originatingType);
Writer writer = sourceFile.openWriter();
writer.write(text);
} finally {
writer.close();
} catch (IOException e) {
processingEnv.getMessager().printMessage(Diagnostic.Kind.WARNING,
"Could not write generated class " + className + ": " + e);
writeSourceFile则会根据原生api将源代码写入本地文件。
MyAutoValue
所以自定义AutoValue也是类似的原理。这里构造MyAutoValue来读取注解的类,生成新的带有get,set和toString方法类。
因为processor的注册只能在jar中使用,不能跟源文件放在一起,所以这里新建了一个来实现MyAutoValue,使用方法在。
定义MyAutoValue。
@Retention(RetentionPolicy.SOURCE)
@Target(ElementType.TYPE)
public @interface MyAutoValue {
MyAutoValueProcessor。同样先在resources/META-INF/services下新建javax.annotation.processing.Processor,并注册MyAutoValueProcessor。
MyAutoValueProcessor继承了AbstractProcessor,并在process中实现了主要的逻辑。
public boolean process(Set&? extends TypeElement& annotations, RoundEnvironment roundEnv) {
Set&? extends Element& elements = roundEnv.getElementsAnnotatedWith(MyAutoValue.class);
if (elements == null || elements.isEmpty()) {
for (Element element : elements) {
if (!(element instanceof TypeElement)) {
processType(element);
} catch (Exception e) {
processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, e.getMessage(), element);
这里去取了所有被MyAutoValue注释的类,并交给processType去处理。
private void processType(Element element) {
TypeElement typeElement = (TypeElement)
String className = element.getSimpleName() + "_MyAutoValue";
TypeSpec.Builder typeSpecBuilder = TypeSpec.classBuilder(className);
typeSpecBuilder.addAnnotation(makeAnnotationSpec());
typeSpecBuilder.addModifiers(Modifier.PUBLIC);
String packageName = getPackageName(typeElement);
makeFieldAndMethod(typeElement, typeSpecBuilder);
} catch (ClassNotFoundException e) {
processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, e.getMessage());
JavaFile.Builder javaFileBuilder = JavaFile.builder(packageName, typeSpecBuilder.build());
String text = javaFileBuilder.build().toString();
JavaFileObject sourceFile = processingEnv.getFiler().createSourceFile(className, element);
Writer writer = sourceFile.openWriter();
writer.write(text);
} finally {
writer.close();
} catch (IOException e) {
processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, e.getMessage());
processType会读取类的字段生成一个新的*_MyAutoValue的类,并根据原有类的字段生成get,set和toString方法,然后将新类写入到本地文件中。
private void makeFieldAndMethod(Element element, TypeSpec.Builder typeSpecBuilder) throws ClassNotFoundException {
List&VariableElement& elementList = ElementFilter.fieldsIn(element.getEnclosedElements());
if (elementList == null || elementList.isEmpty()) {
List&String& fieldList = new ArrayList&&(elementList.size());
for (VariableElement variableElement : elementList) {
String fieldName = variableElement.getSimpleName().toString();
fieldList.add(fieldName);
TypeName typeName = TypeName.get(variableElement.asType());
typeSpecBuilder.addField(makeFieldSpec(fieldName, typeName));
typeSpecBuilder.addMethod(makeSetMethod(fieldName, typeName));
typeSpecBuilder.addMethod(makeGetMethod(fieldName, typeName));
typeSpecBuilder.addMethod(makeToStringMethod(fieldList));
makeFieldAndMethod就是具体的构造字段和方法的逻辑,内部使用JavaPoet实现的,可以参考完整代码和上一篇文章,这里就不列出了。
打包编译,需要注意的META-INF/services的javax.annotation.processing.Processor会阻止javac的编译,打完包会发现里面没有class文件,所以需要加上特殊的参数。
&groupId&org.apache.maven.plugins&/groupId&
&artifactId&maven-compiler-plugin&/artifactId&
&version&2.3.2&/version&
&configuration&
&source&1.7&/source&
&target&1.7&/target&
&encoding&UTF-8&/encoding&
&compilerArgument&-proc:none&/compilerArgument&
&/configuration&
&/plugins&
加上就可以实现完整的打包了。
使用MyAutoValue。在MyAutoValueClassTest类上注解MyAutoValue。
@MyAutoValue
public class MyAutoValueClassTest {
编译完后就会生成以下的新类,会发现自定带上了get,set和toString的方法。
public class MyAutoValueClassTest_MyAutoValue {
public MyAutoValueClassTest_MyAutoValue() {
public void setA(String a) {
public String getA() {
return this.a;
public void setB(String b) {
public String getB() {
return this.b;
public void setC(int c) {
public int getC() {
return this.c;
public String toString() {
return "{\"a\":\"" + this.a + "\",\"b\":\"" + this.b + "\",\"c\":\"" + this.c + "\"}";
dagger的实现跟AutoValue类似,也是根据注解嵌入编译实现新的类,只是AutoValue的逻辑比较简单,只是实现ValueClass的构造,dagger会涉及到更多依赖注入的功能。后面会介绍更多dagger的内容。
阅读(...) 评论()

我要回帖

更多关于 如何使用debug调试 的文章

 

随机推荐