Android关于AutoService、Javapoet讲解
2017-12-20 16:43
507 查看
一、上篇文章提到自定义processor中用到AutoService
文章中我们用到了AutoService,使用@AutoService(Processor.class),编译后AutoService会自动在META-INF文件夹下生成Processor配置信息文件,该文件里就是实现该服务接口的具体实现类。而当外部程序装配这个模块的时候, 就能通过该jar包META-INF/services/里的配置文件找到具体的实现类名,并装载实例化,完成模块的注入。 基于这样一个约定就能很好的找到服务接口的实现类,而不需要再代码里制定,方便快捷。应用依赖如下:
二、javapoet常用api
JavaPoet是square推出的开源java代码生成框架,提供JavaApi生成.java源文件。这个框架功能非常有用,我们可以很方便的使用它根据注解、数据库模式、协议格式等来对应生成代码。通过这种自动化生成代码的方式,可以让我们用更加简洁优雅的方式要替代繁琐冗杂的重复工作。引用依赖:该项目结构如下:
相关类介绍
JavaFile | AJavafilecontainingasingletoplevelclass | 用于构造输出包含一个顶级类的Java文件 |
TypeSpec | Ageneratedclass,interface,orenumdeclaration | 生成类,接口,或者枚举 |
MethodSpec | Ageneratedconstructorormethoddeclaration | 生成构造函数或方法 |
FieldSpec | Ageneratedfielddeclaration | 生成成员变量或字段 |
ParameterSpec | Ageneratedparameterdeclaration | 用来创建参数 |
AnnotationSpec | Ageneratedannotationonadeclaration | 用来创建注解 |
在JavaPoet中,JavaFile是对.java文件的抽象,TypeSpec是类/接口/枚举的抽象,MethodSpec是方法/构造函数的抽象,FieldSpec是成员变量/字段的抽象。这几个类各司其职,但都有共同的特点,提供内部Builder供外部更多更好地进行一些参数的设置以便有层次的扩展性的构造对应的内容
常用api:
addStatement()方法负责分号和换行
beginControlFlow()+endControlFlow()需要一起使用,提供换行符和缩进。
addCode()以字符串的形式添加内
returns添加返回值类型
.constructorBuilder()生成构造器函数
.addAnnotation添加注解
addSuperinterface给类添加实现的接口
superclass给类添加继承的父类
ClassName.bestGuess(“类全名称”)返回ClassName对象,这里的类全名称表示的类必须要存在,会自动导入相应的包
ClassName.get(“包名”,”类名”)返回ClassName对象,不检查该类是否存在
TypeSpec.interfaceBuilder(“HelloWorld”)生成一个HelloWorld接口
MethodSpec.constructorBuilder()构造器
addTypeVariable(TypeVariableName.get(“T”,typeClassName))
会给生成的类加上泛型
占位符
$L代表的是字面量
$SforStrings
$NforNames(我们自己生成的方法名或者变量名等等)
$TforTypes
三、javapoet的使用
publicfinalclassHelloWorld{
publicstaticvoidmain(String[]args){
System.out.println("Hello,JavaPoet!");
}
}
上面的代码我们可以调用javapoet的api方法去生成:
.addModifiers(Modifier.PUBLIC,Modifier.STATIC)
.returns(void.class)
.addParameter(String[].class,"args")
.addStatement("$T.out.println($S)",System.class,"Hello,JavaPoet!")
.build();
TypeSpechelloWorld=TypeSpec.classBuilder("HelloWorld")
.addModifiers(Modifier.PUBLIC,Modifier.FINAL)
.addMethod(main)
.build();
JavaFilejavaFile=JavaFile.builder("com.example.helloworld",helloWorld)
.build();
javaFile.writeTo(System.out);//可以看出,addModifiers对方法的修饰约束,addParameter添加方法参数,addStatement方法体,returns返回值,最后写入java文件中
TypeSpec),fields([code]FieldSpec),方法和构造函数(
MethodSpec),参数(
ParameterSpec)和注释(
AnnotationSpec)提供模型。
[/code]
.addCode(""
+"inttotal=0;\n"
+"for(inti=0;i<10;i++){\n"
+"total+=i;\n"
+"}\n")
.build();
则会生成下面的代码
inttotal=0;
for(inti=0;i<10;i++){
total+=i;
}
}
我们可以子自定义方法去调用
returnMethodSpec.methodBuilder(name)
.returns(int.class)
.addStatement("intresult=0")
.beginControlFlow("for(inti="+from+";i<"+to+";i++)")
.addStatement("result=result"+op+"i")
.endControlFlow()
.addStatement("returnresult")
.build();
}
调用上面的方法后computeRange("multiply10to20",10,20,"*")生成下面的java代码
intresult=0;
for(inti=10;i<20;i++){
result=result*i;
}
returnresult;
}
对于$T泛型,我们的Java程序员喜欢我们的类型:他们让我们的代码更容易理解。JavaPoet在船上。它具有丰富的内置支持类型,包括自动生成
import语句。只是
$T用来引用类型:
importjava.util.Date;
publicfinalclassHelloWorld{
Datetoday(){
returnnewDate();
}
}
要生成上面代码可以用下面的javapoet去实现
.returns(Date.class)
.addStatement("returnnew$T()",Date.class)
.build();
TypeSpechelloWorld=TypeSpec.classBuilder("HelloWorld")
.addModifiers(Modifier.PUBLIC,Modifier.FINAL)
.addMethod(today)
.build();
JavaFilejavaFile=JavaFile.builder("com.example.helloworld",helloWorld)
.build();
javaFile.writeTo(System.out);
JavaPoet支持
importstatic。它通过明确收集类型成员名称来完成。见下面代码:
.addStaticImport(hoverboard,"createNimbus")
.addStaticImport(namedBoards,"*")
.addStaticImport(Collections.class,"*")
.build();
如果我们想生成构造Constructors,也很简单:
privatefinalStringgreeting;
publicHelloWorld(Stringgreeting){
this.greeting=greeting;
}
}
要实现上面java代码,用javapoet去实现,如下:
.addModifiers(Modifier.PUBLIC)
.addParameter(String.class,"greeting")
.addStatement("this.$N=$N","greeting","greeting")
.build();
TypeSpechelloWorld=TypeSpec.classBuilder("HelloWorld")
.addModifiers(Modifier.PUBLIC)
.addField(String.class,"greeting",Modifier.PRIVATE,Modifier.FINAL)
.addMethod(flux)
.build();
还可定义枚举类
.addModifiers(Modifier.PUBLIC)
.addEnumConstant("ROCK")
.addEnumConstant("SCISSORS")
.addEnumConstant("PAPER")
.build();
publicenumRoshambo{
ROCK,
SCISSORS,
PAPER
}
还有匿名内部类的实现
.addSuperinterface(ParameterizedTypeName.get(Comparator.class,String.class))
.addMethod(MethodSpec.methodBuilder("compare")
.addAnnotation(Override.class)
.addModifiers(Modifier.PUBLIC)
.addParameter(String.class,"a")
.addParameter(String.class,"b")
.returns(int.class)
.addStatement("return$N.length()-$N.length()","a","b")
.build())
.build();
TypeSpechelloWorld=TypeSpec.classBuilder("HelloWorld")
.addMethod(MethodSpec.methodBuilder("sortByLength")
.addParameter(ParameterizedTypeName.get(List.class,String.class),"strings")
.addStatement("$T.sort($N,$L)",Collections.class,"strings",comparator)
.build())
.build();
Thisgeneratesamethodthatcontainsaclassthatcontainsamethod:
voidsortByLength(List<String>strings){
Collections.sort(strings,newComparator<String>(){
@Override
publicintcompare(Stringa,Stringb){
returna.length()-b.length();
}
});
}
也可创建注解:
.addAnnotation(Override.class)
.returns(String.class)
.addModifiers(Modifier.PUBLIC)
.addStatement("return$S","Hoverboard")
.build();
//结果如下:
@Override
publicStringtoString(){
return"Hoverboard";
}
创建注释javadoc
.addJavadoc("Hides{@codemessage}fromthecaller'shistory.Other\n"
+"participantsintheconversationwillcontinuetoseethe\n"
+"messageintheirownhistoryunlesstheyalsodeleteit.\n")
.addJavadoc("\n")
.addJavadoc("<p>Use{@link#delete($T)}todeletetheentire\n"
+"conversationforallparticipants.\n",Conversation.class)
.addModifiers(Modifier.PUBLIC,Modifier.ABSTRACT)
.addParameter(Message.class,"message")
.build();
/**
*Hides{@codemessage}fromthecaller'shistory.Other
*participantsintheconversationwillcontinuetoseethe
*messageintheirownhistoryunlesstheyalsodeleteit.
*
*<p>Use{@link#delete(Conversation)}todeletetheentire
*conversationforallparticipants.
*/
voiddismiss(Messagemessage);
用法很多,还可以用FieldSpec.builder创建属性变量,ParameterSpec创建方法参数
四、总结问题
如果我们在自定义processor的时候找不到javax.annotation.processing.*包下的类,则创建javamodule而非androidmodule相关文章推荐
- Android关于AutoService、Javapoet讲解
- Android关于AutoService、Javapoet讲解
- 四、关于Java、Android编程平台的搭建问题讲解之环境配置
- Development and remote installation of Java service for the Android Devices
- 关于在android中service开发的IllegalArgumentException错误和服务无法启动的解释
- 关于java调用.Net WCF服务的讲解(一)
- 关于JAVA和Android的JNI的使用
- 关于java.awt.datatransfer包的一些讲解
- android中service的使用方法-小例子讲解
- Android页面跳转实现方法讲解(纯java)
- 为 Android 添加 Java 层服务也就是添加自定义的aidl服务到serviceManager 通过ServiceManager.getService取
- 关于Java的return continue break语句的讲解
- 关于 Android中googleMaps的Geocoder, “the service is not available”解决办法
- 关于Android程序的java.lang.RuntimeException: Unable to instantiate activity ComponentInfo错误
- 关于Java的return continue break语句的讲解
- 关于java调用.Net WCF服务的讲解(二)
- 关于线程的讲解?(出自Java原著)
- Android学习中关于WindowManager的讲解(转载)
- 关于线程的讲解?(出自Java原著)
- Android开发:关于导入ApiDemos后没有R.java文件的问题