如何停止时间:亲吻。
如何时间旅行:阅读。
如何逃脱时间:音乐。
如何感受时间:写作。
如何释放时间:呼吸。
Android使用注解生成器生成Java代码~
关于反射的基础知识可见:第12章 元编程与注解、反射 《Kotlin 项目实战开发》
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"
@Target({METHOD, CONSTRUCTOR})
@Retention(CLASS)
public @interface XAnnotation {
}
Java Library
,名称叫做x_compiler
。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"
手动注册
javax.annotation.processing.Processor
mkdir -p src/main/resources/META-INF/services/
cd src/main/resources/META-INF/services/
touch javax.annotation.processing.Processor
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
主动注册
需要在gradle中依赖谷歌提供的库:
compileOnly 'com.google.auto.service:auto-service:1.0-rc5'
在自定义的Processor上增加注解即可。
@AutoService(Processor::class)
class SuperChannelCompiler : AbstractProcessor() {
}
这里使用了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 {
}
在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文件。