Annotation Processor

android-apt 與 AnnotationProcessor

APT(Annotation Processing Tool)是一種處理注釋的工具,它對源代碼文件進行檢測找出其中的Annotation,使用Annotation進行額外的處理。(額外的處理包括,修改源文件,增加新代碼,甚至添加新的Annotation)

android-apt是一個gradle插件,始于三年前 ByHugo*Visser*

AnnotationProcessor是Android Gradle 插件 2.2 版本提供的插件

能干什么?

少些代碼(增加開發(fā)效率,代碼看起來更優(yōu)雅)

解耦(ActivityRouter)

誰都在用?

EventBus、Retrofit、Dagger2、ButterKnife等等

像官方靠齊,本文均采用AnnotationProcessor進行示范

初體驗:

AnnotationProcessor 所需環(huán)境:

gradle 插件2.2 +

AndroidStudio 2.2 (AndroidStudio 2.3調(diào)試不成功,未知原因)

所需知識:

Java注解知識(https://joyrun.github.io/2016/07/18/java-annotation)JavaPoet(http://www.itdecent.cn/p/95f12f72f69a)

1、Gradle插件

buildscript{repositories{? ? ? ? jcenter()? ? }dependencies{classpath'com.android.tools.build:gradle:2.2.1'}}

2、新建Annotation定義的Module

build.gradle定義如下:

apply plugin:'java'dependencies{compilefileTree(dir:'libs',include: ['*.jar'])}sourceCompatibility="1.7"targetCompatibility="1.7"

當然你也可以不新建一個Module來做,寫在業(yè)務(wù)Module里,但是Compiler要依賴,所以不建議寫在也業(yè)務(wù)里。

3、新建注解處理Module

build.gradle定義如下:

applyplugin:'java'dependencies{compilefileTree(include: ['*.jar'],dir:'libs')compile'com.google.auto.service:auto-service:1.0-rc2'compile'com.squareup:javapoet:1.7.0'compileproject(':annotation')}sourceCompatibility="1.7"targetCompatibility="1.7"

auto-service:可以將自定義的Compiler自動注冊進去

javapoet:優(yōu)雅的生成Java類的工具

compile project(':annotation') 依賴剛才新建的annotation module 因為需要引用annotation

注解處理是整個Annotation Processor的核心,對Annotation進行處理的就是這個部分。

繼承Java提供的AbstractProcessor,重寫相關(guān)方法就可以實現(xiàn)對Annotation的處理

@AutoService(Processor.class)publicclassUrlCompilerextendsAbstractProcessor{privatestaticfinalStringPACKAGE="com.baidu.appsearch.config";privatestaticfinalStringCLASSNAME_SUFFIX="Injection";@OverridepublicSet getSupportedAnnotationTypes() {returnCollections.singleton(UrlClass.class.getCanonicalName());}@Overridepublic boolean process(Setannotations, RoundEnvironment roundEnv) {for(Elementelement : roundEnv.getElementsAnnotatedWith(UrlClass.class)) {TypeElement typeElement = (TypeElement) element;ListelementList = typeElement.getEnclosedElements();HashMap urls =newHashMap<>();for(Elemente : elementList) {Urlurl = e.getAnnotation(Url.class);if(url !=null) {if(!url.value().startsWith("/") && !url.value().startsWith("http")) {thrownewRuntimeException("url should start with / or http");}VariableElement variableElement = (VariableElement) e;urls.put(variableElement.getConstantValue().toString(), url.value());}}MethodSpec constructor = MethodSpec.constructorBuilder().addModifiers(Modifier.PUBLIC).build();StringBuilder sb =newStringBuilder();Iteratoriter = urls.entrySet().iterator();while(iter.hasNext()) {Map.Entry entry = (Map.Entry) iter.next();Objectkey = entry.getKey();Objectval = entry.getValue();sb.append("urls.put(\"").append(key).append("\"").append(",\"").append(val).append("\");");}intinitialCapacity = urls.size();MethodSpec init = MethodSpec.methodBuilder("init").addModifiers(Modifier.PUBLIC).addAnnotation(Override.class).returns(HashMap.class).addCode("HashMap urls = new HashMap("+ initialCapacity +");"+ sb.toString()).addCode("return urls;").build();StringclassNameStr = typeElement.getSimpleName().toString();ClassName className = ClassName.get(PACKAGE,CLASSNAME_SUFFIX);TypeSpec settingManager = TypeSpec.classBuilder(classNameStr +CLASSNAME_SUFFIX).addModifiers(Modifier.PUBLIC, Modifier.FINAL).addSuperinterface(className).addMethod(constructor).addMethod(init).build();Stringfull = typeElement.getQualifiedName().toString();StringpackageName = full.substring(0, full.indexOf(classNameStr)-1);JavaFile javaFile = JavaFile.builder(packageName, settingManager).build();try{javaFile.writeTo(processingEnv.getFiler());}catch(IOException e) {e.printStackTrace();}}returntrue;}@OverridepublicSourceVersion getSupportedSourceVersion() {returnSourceVersion.RELEASE_7;}@Overridepublic synchronizedvoidinit(ProcessingEnvironment processingEnv) {super.init(processingEnv);}}

其中的process方法就是處理Annotation的核心方法,可以獲取到Annotation,與反射的思路類似。

4、運行

運行之后會自動生成Processor處理后的java類

怎么調(diào)試?

如何調(diào)試process方法?這和一般App調(diào)試是不一樣的,因為process方法是運行在編譯期,所以需要配置遠程調(diào)試。

新建一個調(diào)試

其他保持默認即可

配置要調(diào)試的Task

復(fù)制進去剛才remote的command參數(shù),注意suspend改成y

在process方法里加斷點

點擊運行

點擊啟動調(diào)試器,過會兒就會在斷點停住了

參考資料:

1、http://www.itdecent.cn/p/2494825183c5

2、http://blog.csdn.net/tomatomas/article/details/53998585

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

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