Kotlin注解使用

Kotlin的注解和java的基本一致, 具體的細(xì)節(jié)可以看官方文檔

https://kotlinlang.org/docs/reference/annotations.html

比較大的區(qū)別是Kotlin不支持@Inherited元注解,雖然一般情況下從父類(lèi)使用注解的情況是非常少的。但總有人會(huì)碰到這樣的問(wèn)題。已經(jīng)有人提出這個(gè)問(wèn)題了,詳見(jiàn):https://youtrack.jetbrains.com/issue/KT-22265

注解的使用

注解一般用來(lái)在編譯時(shí)處理代碼,例如編譯時(shí)進(jìn)行格式檢查,生成文檔等
Kotlin的注解和Java的注解使用方式基本一致。獲取注解相關(guān)信息的方式也基本一致
都需要實(shí)現(xiàn)AbstractProcessor來(lái)獲取帶指定的注解的元素的信息

public class AProcessor extends AbstractProcessor {

    @Override
    public synchronized void init(ProcessingEnvironment env){ }

    @Override
    public boolean process(Set<? extends TypeElement> annoations, RoundEnvironment env) { }

    @Override
    public Set<String> getSupportedAnnotationTypes() { }

    @Override
    public SourceVersion getSupportedSourceVersion() { }

}
  • init Processor初始化的時(shí)候會(huì)調(diào)用此方法, ProcessingEnvironment是Processor所處的環(huán)境. ProcessingEnvironment有一個(gè)Options字段,用來(lái)存放一些特定的選項(xiàng),例如可以從gradle插件中傳遞Project的一些信息進(jìn)來(lái).
android.defaultConfig.javaCompileOptions.annotationProcessorOptions.argument(“moduleName”, project.name)
  • process 是處理注解的主要方法,annoations中包含注解和使用注解的元素的信息,RoundEnvironment包含當(dāng)前注解環(huán)境的上下文信息。return true表示該注解已處理完成,不再需要其他Processor處理

  • getSupportedAnnotationTypes 告訴Processor要掃面那些注解,返回的是包含指定注解類(lèi)名的set

  • getSupportedSourceVersion 指定支持的version, 不同的Version支持的內(nèi)容不一樣,

1.1: nested classes
1.2: strictfp
1.3: no changes
1.4: assert
1.5: annotations, generics, autoboxing, var-args...
1.6: no changes
1.7: diamond syntax, try-with-resources, etc.
1.8: lambda expressions and default methods

一般傳入SourceVersion.latest()即可

獲取注解的信息

在process方法中可以獲取到指定注解的信息。annoations 中的對(duì)象是TypeElement, TypeElement 是Element的子類(lèi),里面包含著注解的信息.

通過(guò)roundEnvironment.getElementsAnnotatedWith(注解類(lèi)的Class)來(lái)獲取當(dāng)前注解的信息

Element的關(guān)鍵屬性:

  • name: 使用注解的元素的名稱(chēng)。如果是CLASS就是類(lèi)全名,如果是方法就是方法名,其他類(lèi)推
  • getKind(): 使用注解的元素類(lèi)型,如CLASS, PACKAGE, INTERFACE,FIELD等,對(duì)應(yīng)注解的Target
  • getModifiers(): 使用注解的元素的修飾符,如class的private, static, final等
  • TypeMirror:對(duì)應(yīng)Java 編程語(yǔ)言中的類(lèi)型。 如ArrayType,DeclaredType,NullType等。主要用來(lái)判斷使用者和注解參數(shù)的類(lèi)型,通過(guò)typeMirror可以獲取注解中Class參數(shù)的類(lèi)名

注冊(cè)Processor

AbstractProcessor實(shí)現(xiàn)之后不能直接使用,需要注冊(cè)之后才能運(yùn)行,有兩種方式:

  1. 手動(dòng)注冊(cè)

在實(shí)現(xiàn)AbstractProcessor的項(xiàng)目中添加resources/META-INF文件夾,并在META-INF下添加一個(gè)名稱(chēng)為javax.annotation.processing.Processor的文本文件,在里面寫(xiě)入實(shí)現(xiàn)AbstractProcessor類(lèi)的全名

  1. 自動(dòng)注冊(cè)

使用google提供的AutoService主動(dòng)注冊(cè)。在AbstractProcessor實(shí)現(xiàn)類(lèi)上加上注解:

@AutoService(Processor::class)

就可以了。

AutoService也是通過(guò)注解的形式自動(dòng)生成對(duì)應(yīng)的文件和文件夾。

打印日志

由于AbstractProcessor的執(zhí)行在編譯器,所以不能直接使用android和java的日志輸出方式,需要使用

processingEnv.messager.printMessage(Diagnostic.Kind, msg)

來(lái)打印日志

注意: 若使用Diagnostic.Kind.ERROR打印,則會(huì)導(dǎo)致編譯失敗。

生成代碼

注解的信息收集完成之后是不能直接使用的,因?yàn)槭窃诰幾g期間,無(wú)法直接保存信息到運(yùn)行期。所以需要生成對(duì)應(yīng)的代碼老保存需要的信息和功能

AbstractProcessor中提供了生成代碼的輔助類(lèi):Filer, 在ProcessingEnvironment中。生成代碼就是一個(gè)簡(jiǎn)單的創(chuàng)建文件,寫(xiě)入文本內(nèi)容的過(guò)程。生成java源碼有很著名的javapoet框架,不再贅述。

在kotlin中運(yùn)行Processor時(shí)kapt, 來(lái)替代annotationProcessor。 也有KotlinPoet來(lái)對(duì)應(yīng)javapoet。
生成代碼還是比較方便的

當(dāng)然,如果需要生成的源碼文件比較簡(jiǎn)單,可以直接使用拼接字符串的形式生成代碼,然后寫(xiě)入到文件中。

自動(dòng)生成的源碼文件在build文件夾下面,kotlin生成的文件的文件夾路徑可以在options中獲取到:

val path = processingEnv.options[“kapt.kotlin.generated”]

文件生成之后,在開(kāi)發(fā)期間就可以直接使用該類(lèi)了

由于通過(guò)注解能獲取的信息的類(lèi)型是非常有限的,而且最終都是以寫(xiě)入文件的形式保存,所以能保存的信息比較有限,用的最多的也就是來(lái)獲取類(lèi)名,寫(xiě)入到文件中,反射使用。當(dāng)然,生成的代碼要實(shí)現(xiàn)的功能還是可以更加豐富的,如ButterKnife,Router, dagger等

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容