前言
Android使用註解生成器生成Java代碼~
- 官方介紹:添加註釋處理器。
接入流程
創建Annotation
關於反射的基礎知識可見:第12章 元編程與註解、反射 《Kotlin 項目實戰開發》
- 在Android Studio中創建一個
Java Library
,名稱叫做x_annotation
。 x_annotation
的Gradle的配置如下:
apply plugin: 'java-library'
apply plugin: 'kotlin'
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
}
sourceCompatibility = "7"
targetCompatibility = "7"
- 之後,在Library中定義一些註解。
@Target({METHOD, CONSTRUCTOR})
@Retention(CLASS)
public @interface XAnnotation {
}
創建Compiler
- 在Android Studio中創建一個
Java Library
,名稱叫做x_compiler
。
配置Gradle
x_compiler
的Gradle的配置如下:
apply plugin: 'java-library'
apply plugin: 'kotlin'
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
// JavaPoet is a Java API for generating .java source files.
// 源碼:https://github.com/square/javapoet
implementation 'com.squareup:javapoet:1.12.1'
implementation project(':x_annotation')
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
}
sourceCompatibility = "7"
targetCompatibility = "7"
註冊Processor
手動註冊
- 創建
javax.annotation.processing.Processor
- 創建文件夾:
mkdir -p src/main/resources/META-INF/services/
- 進入目錄:
cd src/main/resources/META-INF/services/
- 創建文件:
touch javax.annotation.processing.Processor
- 在文件中增加Process的包名和類名:
com.notzuonotdied.flutter.x_compiler.XCompiler
- 創建文件夾:
➜ android git:(master) ✗ tree x_compiler
super_channel_compiler
├── build.gradle
├── libs
├── src
│ └── main
│ ├── java
│ │ └── com
│ │ └── notzuonotided
│ │ └── flutter
│ │ └── x_compiler
│ │ └── XCompiler.kt
│ └── resources
│ └── META-INF
│ └── services
│ └── javax.annotation.processing.Processor
└── super_channel_compiler.iml
11 directories, 4 files
- 看看文件的內容:
➜ services git:(master) ✗ cat javax.annotation.processing.Processor
com.notzuonotdied.flutter.x_compiler.XCompiler
主動註冊
在自定義的Processor上增加註解即可。
@AutoService(Processor::class)
class SuperChannelCompiler : AbstractProcessor() {
}
自定義Processor
這裏使用了JavaPoet,如果不懂的,可以見這份使用文檔:JavaPoet的使用指南。
src/main/java/com/notzuonotdied/flutter/x_compiler/XCompiler.kt
的實現如下:
import java.util.*
import java.io.IOException
import javax.annotation.processing.*
import javax.lang.model.element.Modifier
import javax.lang.model.element.TypeElement
import javax.lang.model.util.Elements
import com.squareup.javapoet.JavaFile
import com.squareup.javapoet.TypeSpec
class SuperChannelCompiler : AbstractProcessor() {
/**
* 文件相關的輔助類
*/
private var mFiler: Filer? = null
/**
* 元素相關的輔助類
*/
private var mElementUtils: Elements? = null
/**
* 日誌相關的輔助類
*/
private var mMessager: Messager? = null
/**
* 這個函數會被註解生成器調用,在這裏初始化需要的一些變量
*
* @param processingEnvironment
*/
@Synchronized
override fun init(processingEnvironment: ProcessingEnvironment) {
super.init(processingEnvironment)
mElementUtils = processingEnv.elementUtils
mMessager = processingEnv.messager
mFiler = processingEnv.filer
}
/**
* 生成代碼
* */
override fun process(set: Set<TypeElement?>, roundEnvironment: RoundEnvironment): Boolean {
val finderClass = TypeSpec.classBuilder("XGeneratedClass")
.addModifiers(Modifier.PUBLIC)
.build()
try {
JavaFile.builder("com.notzuonotdied.flutter.x_compile", finderClass)
.addFileComment("Generated code from x_compile Do not modify!")
.build()
.writeTo(mFiler)
} catch (e: IOException) {
e.printStackTrace()
}
return true
}
/**
* 責任鏈模式:用於判斷這個是否由該註解生成器處理
*/
override fun getSupportedAnnotationTypes(): Set<String> {
val types: MutableSet<String> = LinkedHashSet()
types.add(XAnnotation::class.java.canonicalName)
return types
}
}
使用
在主工程的Gradle中配置如下:
dependencies {
implementation project(":x_annotation")
annotationProcessor project(":x_compiler")
}
在主工程中使用x_annotation
定義的註解,點擊編譯即可。編譯完成後,可以在工程下的/build/app/generated/ap_generated_sources/debug/out/com/notzuonotdied/flutter/x_compile
目錄看到我們生成的類XGeneratedClass
,文件內容如下:
// Generated code from x_compile Do not modify!
package com.notzuonotdied.flutter.x_compile;
public class XGeneratedClass {
}
- 大功告成,_
支持Kotlin
在Butter Knife中可以看到一句話,If you are using Kotlin, replace annotationProcessor
with kapt
。我們的註解器也一樣,如果要支持Kotlin,也需要使用kapt
。在主工程的Gradle中配置如下:
apply plugin: 'kotlin-kapt'
dependencies {
implementation project(":x_annotation")
kapt project(":x_compiler")
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
}
注意: 如果你不使用kapt
,那麼你的RoundEnvironment
中是找不到kclass
的。即沒辦法找到Kotlin的class文件。
JavaPoet使用教程
附錄
- Android 學習使用annotationprocessor自動生成java文件
- Java註解解析-搭建自己的註解處理器(CLASS註解使用篇)
- JavaPoet is a Java API for generating .java source files.
- Java Annotation Processor 小記