對於我來講,JavaPoet也是不經意間發現的,平常Android開發中:java
主要使用Mvp+RxJava+Dagger2這套框架
複製代碼
在這套框架裏每次寫Activity或者Fragment就會寫一套Mvp+Compent+Module,以下圖:android
通過長時間的重複編寫,發現這一套Mvp+Compent+Module文件,只有名稱是變化的,因此只須要將名稱抽象出來,其餘只需模板化,就能生成出上述Java文件.編程
正當想怎麼可以快捷生成Java文件,這時JavaPoet便出現,並且JavaPoet可以徹底知足需求。bash
本文主要以JavaPoet的使用方法介紹爲主,會將JavaPoet的基本API都介紹一遍,你也能夠理解成JavaPoet的中文簡易教程app
(1)JavaPoet是一款能夠自動生成Java文件的第三方依賴 (2)簡潔易懂的API,上手快 (3)讓繁雜、重複的Java文件,自動化生成,提升工做效率,簡化流程框架
爲了展現JavaPoet的能力,這裏以自動生成一個全新的MainActivity爲例。ide
public class MainActivity extends Activity{
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
複製代碼
我在使用JavaPoet的時候,習慣從外向內逐一輩子成,可是這不是標準,這裏能夠按照本身的方式來理解和生成.ui
public static void main(String[] args) {
ClassName activity = ClassName.get("android.app", "Activity");
TypeSpec.Builder mainActivityBuilder = TypeSpec.classBuilder("MainActivity")
.addModifiers(Modifier.PUBLIC)
.superclass(activity);
ClassName override = ClassName.get("java.lang", "Override");
ClassName bundle = ClassName.get("android.os", "Bundle");
ClassName nullable = ClassName.get("android.support.annotation", "Nullable");
ParameterSpec savedInstanceState = ParameterSpec.builder(bundle, "savedInstanceState")
.addAnnotation(nullable)
.build();
MethodSpec onCreate = MethodSpec.methodBuilder("onCreate")
.addAnnotation(override)
.addModifiers(Modifier.PROTECTED)
.addParameter(savedInstanceState)
.addStatement("super.onCreate(savedInstanceState)")
.addStatement("setContentView(R.layout.activity_main)")
.build();
TypeSpec mainActivity = mainActivityBuilder.addMethod(onCreate)
.build();
JavaFile file = JavaFile.builder("com.test", mainActivity).build();
try {
file.writeTo(System.out);
} catch (IOException e) {
e.printStackTrace();
}
}
複製代碼
經過在Main方法中運行以上的代碼,就能夠直接生成出MainActivity對象,自上而下的觀察上述代碼,你會發現JavaPoet讓java文件變得有邏輯性。編碼
addModifiers(Modifier... modifiers)
複製代碼
Modifier是一個枚舉對象,枚舉值爲修飾關鍵字Public、Protected、Private、Static、Final等等。 全部在JavaPoet建立的對象都必須設置修飾符(包括方法、類、接口、枚舉、參數、變量)。spa
addAnnotation(AnnotationSpec annotationSpec)
addAnnotation(ClassName annotation)
addAnnotation(Class<?> annotation)
複製代碼
該方法即爲類或方法或參數設置註解,參數便可以是AnnotationSpec,也能夠是ClassName,還能夠直接傳遞Class對象。 通常狀況下,包含複雜屬性的註解通常用AnnotationSpec,若是單純添加基本註解,無其餘附加屬性能夠直接使用ClassName或者Class便可。
addJavadoc(CodeBlock block)
addJavadoc(String format, Object... args)
複製代碼
在編寫類、方法、成員變量時,能夠經過addJavadoc來設置註釋,能夠直接傳入String對象,或者傳入CodeBlock(代碼塊)。
在JavaPoet中生成類、接口、枚舉,必須得經過TypeSpec生成,而classBuilder、interfaceBuilder、enumBuilder即是建立其關鍵的方法:
建立類:
TypeSpec.classBuilder("類名「)
TypeSpec.classBuilder(ClassName className)
建立接口:
TypeSpec.interfaceBuilder("接口名稱")
TypeSpec.interfaceBuilder(ClassName className)
建立枚舉:
TypeSpec.enumBuilder("枚舉名稱")
TypeSpec.enumBuilder(ClassName className)
複製代碼
繼承類:
.superclass(ClassName className)
實現接口
.addSuperinterface(ClassName className)
複製代碼
繼承存在泛型的父類
當繼承父類存在泛型時,須要使用ParameterizedTypeName
ParameterizedTypeName get(ClassName rawType, TypeName... typeArguments) 複製代碼
返回的ParameterizedTypeName對象,已經被添加泛型信息
addMethod(MethodSpec methodSpec)
複製代碼
經過配置MethodSpec對象,使用addMethod方法將其添加進TypeSpec中。
addEnumConstan(String enumValue)
複製代碼
經過addEnumConstan方法添加枚舉值,參數爲枚舉值名稱。
JavaPoet生成成員變量是經過FieldSpec的build方法生成.
builder(TypeName type, String name, Modifier... modifiers)
複製代碼
只要傳入TypeName(Class)、name(名稱)、Modifier(修飾符),就能夠生成一個基本的成員變量。
成員變量通常來講由註解(Annotation)、修飾符(Modifier)、Javadoc(註釋)、initializer(實例化)。
addAnnotation(TypeName name)
複製代碼
addModifiers(Modifier ...modifier)
複製代碼
addJavadoc(String format, Object... args)
複製代碼
因爲上述三個方法,都在通用方法介紹過這裏就再也不重複介紹。
initializer(String format, Object... args)
複製代碼
即成員變量的實例化,例:
public Activity mActivity = new Activity;
複製代碼
而initializer方法中的內容就是「=」後面的內容,下面看下具體的代碼實現,上面的成員變量:
ClassName activity = ClassName.get("android.app", "Activity");
FieldSpec spec = FieldSpec.builder(activity, "mActivity")
.addModifiers(Modifier.PUBLIC)
.initializer("new $T", activity)
.build();
複製代碼
JavaPoet生成方法分爲兩種,第一種是構造方法,另外一種爲常規的方法。
MethodSpec.constructorBuilder()
複製代碼
MethodSpec.methodBuilder(String name)
複製代碼
方法的主要構成有方法參數、註解、返回值、方法體、拋出異常五種,註解能夠參考通用方法addAnnotation,其餘方法咱們將會一一介紹:
addParameter(ParameterSpec parameterSpec)
複製代碼
設置方法參數的方法經過addParameterSpec來實現,ParameterSpec的具體使用參考下一小節。
returns(TypeName returnType)
複製代碼
設置方法的返回值,只需傳入一個TypeName對象,而TypeName是ClassName,ParameterizedTypeName的基類。
在JavaPoet中,設置方法體內容有兩個方法,分別是addCode和addStatement:
addCode()
addStatement()
複製代碼
這兩個本質上都是設置方法體內容,可是不一樣的是使用addStatement()方法時,你只須要專一於該段代碼的內容,至於結尾的分號和換行它都會幫你作好。 而addCode()添加的方法體內容就是一段無格式的代碼片,須要開發者本身添加其格式。
在JavaPoet中,設置方法體使用模板是比較常見的,由於addCode和addStatement方法都存在這樣的一個重載:
addCode(String format, Object... args)
addStatement(String format, Object... args)
複製代碼
在JavaPoet中,format中存在三種特定的佔位符:
$T 在JavaPoet代指的是TypeName,該模板主要將Class抽象出來,用傳入的TypeName指向的Class來代替。
ClassName bundle = ClassName.get("android.os", "Bundle");
addStatement("$T bundle = new $T()",bundle)
複製代碼
上述添加的代碼內容爲:
Bundle bundle = new Bundle();
複製代碼
$N在JavaPoet中代指的是一個名稱,例如調用的方法名稱,變量名稱,這一類存在乎思的名稱
addStatement("data.$N()",toString)
複製代碼
上述代碼添加的內容:
data.toString();
複製代碼
$S在JavaPoet中就和String.format中%s同樣,字符串的模板,將指定的字符串替換到$S的地方
.addStatement("super.$S(savedInstanceState)","onCreate")
複製代碼
即將"onCreate"字符串代替到$S的位置上.
.addException(TypeName name)
複製代碼
設置方法拋出異常,可使用addException方法,傳入指定的異常的ClassName,便可爲該方法設置其拋出該異常.
JavaPoet生成有參方法時,須要填充參數,而生成參數則須要經過ParameterSpec這個類。
addParameter(ParameterSpec parameterSpec)
複製代碼
ParameterSpec.builder(TypeName type, String name, Modifier... modifiers)
複製代碼
給參數設置其Class,以及參數名稱,和修飾符.
一般來講參數的構成包括:參數的類型(Class)、參數的名稱(name)、修飾符(modifiers)、註解(Annotation)
除了builder方法初始化類型、以及名稱、修飾符以外,其他能夠經過以下方法進行設置:
.addModifiers(Modifier modifier)
複製代碼
addAnnotation(TypeName name)
複製代碼
添加修飾符、註解具體使用可參考通用方法。
在JavaPoet建立類、成員變量、方法參數、方法,都會用到註解。
若是使用不包含屬性的註解能夠直接經過
.addAnnotation(TypeName name)
複製代碼
直接傳入TypeName或者Class進行設置。
若是使用的註解包含屬性,而且不止一個時,這時候就須要生成AnnotationSpec來解決,下面簡單瞭解下AnnotationSpec。
AnnotationSpec.builder(ClassName type)
複製代碼
能夠發現初始化,只需傳入ClassName或者Class便可。
addMember(String name, String format, Object... args)
複製代碼
使用addMember能夠設置註解的屬性值,name對應的就是屬性名稱,format的內容即屬性體,一樣方法體的格式化在這裏也是適用的。
若是上述內容你已經看完,那麼恭喜你,你已經明白JavaPoet的意圖,可是如今的你,還差最後一步,即如何生成代碼。
JavaPoet中負責生成的類是JavaFile
JavaFile.builder(String packageName, TypeSpec typeSpec)
複製代碼
JavaFile經過向build方法傳入PackageName(Java文件的包名)、TypeSpec(生成的內容)生成。
javaFile.writeTo(System.out)
複製代碼
生成的內容會輸出到控制檯中
javaFile.writeTo(File file)
複製代碼
生成的內容會以java文件的方式,存放到你傳入File文件的位置
當你讀完了本文,若是你產生下面的想法:
那麼說明你已經對JavaPoet感興趣了,能夠本身動手嘗試一下,感覺下JavaPoet的魅力。
最後貼一張,JavaPoet祕籍,有了它會很好的幫助你使用JavaPoet.
(註明:該圖來自walfud的我的博客)