拓展篇:注解处理器最佳实践

基础篇中,我们介绍了什么是注解以及如何开发注解处理器,今天就来说说在开发编译时注解处理器中的那些最佳实践。

什么是Android-apt

我们知道APT是集成在javac当中的工具,这个Android-apt又是什么鬼呢? 对于从事Android开发的同学来说,ButterKnife这个开源工具可是非常熟悉。在使用该工具之前,你需要进行配置:

compile 'com.jakewharton:butterknife:8.4.0'
apt 'com.jakewharton:butterknife-compiler:8.4.0'

这里的有什么用?我们在上一节中没有配置apt插件照样可以用,这是怎么一回事?
Anroid-apt是用在Android Studio中处理注解处理的插件。它有两方面的作用:

  1. 只允许配置编译时注解处理器依赖,但在最终APK或者Library中不包含注解处理器的代码。
  2. 设置源路径,以便由注解处理器生成的代码能被Android Studio识别。

另外,一些注解处理器可以接受外部的参数,在IDEA当中我们可以直接配置,但是基于IDEA而来的Android Studio反而无法直接配置,借助Android-apt插件我们可以实现该功能,其用法如下:

apt{
    arguments{
        配置参数名称 参数值
    }

}

对与在一个jar包中的注解处理器(API和处理器)而言,我们不需要进行特殊的配置,它照样可以工作。如果我们需要在项目当中引用注解处理器生成的代码,那么就需要使用Android-apt插件来帮助解决。

对于Butter Knife,EventBus 3.0这类工具,最终我们都需要在自己项目引用注解处理器生成的代码,因此需要为其配置Android-apt。EventBus 3.0的注解处理器还接受两个参数,当然也要借助Android-apt插件了,以EventBus在工程的配置为例:


这里写图片描述

到现在,我们恍然大雾,原来Android-apt是这么用的啊。知其然更知其所以然啊,现在无论你遇到什么样的配置问题,那都是小菜一碟。

你正在为自己明白了Android-apt的用途的时候,无意间听到了消息:android-apt插件作者近期已经发表声明表示后续不会再继续维护该插件。

噩耗就是来的这么随心所欲啊!!!好不容易懂了,结果发现这玩意不再更新,这是什么梗什么怨啊。


这里写图片描述

什么是annotationProcessor

Gradle从2.2版本开始支持annotationProcessor功能来代替Android-apt。另外,和android-apt只支持javac编译器相比,annotationProcessor同时支持javac和jack编译器。

和Android-apt使用相比,annotationProcessor使用更为简单,还是以EventBus的配置为例:


这里写图片描述

不难看出,使用annotationProcessor更为简单。如果你现在的Gradle版本是2.2.X以上,可以考虑替换掉Android-apt了。


如何划分项目结构

由于编译时注解处理器只在编译过程中使用,因此我们不希望注解处理器相关的代码在最终的APK中存在,这样能够有效的较少方法数。比如我通常在编写注解Annotation Processor的时候会引用javapoet和Guava,如果将这些代码也打进最终的APK中会造成方法数的暴增,因此建议将注解处理器相关代码单独成为一个模块。

另外为了方面注解被其他工程引用,通常我也建议将注解的定义单独划分成一个模块。

综上,我们最终的项目结构如下:

  • xxx/xxx-api:主工程/提供api,Android Library类型
  • xxx-compiler:注解处理器模块,Java Library类型
  • xxx-annotations:自定义注解,Java Library类型

xxx/xxx-api依赖xxx-annotations,xxx-compiler依赖xxx-annotations。这点Butter Knife给我们一个非常好的示范:

这里写图片描述


替换jar为moudle依赖

基础篇中我们说道,最终要讲注解处理器打成jar包。这样太麻烦了,总不能每次修改都要重新打个jar包吧,然后拷贝吧?

其实在Android Studio当中我们同样可以采用moudle依赖的形式,这和我们以前依赖其他模块并没有太大的区别,比如我们在需要注解处理器的地方依赖apt即可:

compile project(":apt")

但要在注解处理器moudle中的build.gradle文件中,配置:

sourceCompatibility = "1.7"
targetCompatibility = "1.7"
 

但是这样我们的注解处理器就会被打包到apk当中,现在就可以利用上面说的Android-apt了。


使用@AutoService注解简化配置

基础篇中,我们说道需要注册处理器,虽然没什么难度,但是弄不好一个粗心就写错了,有没有什么更好的方式呢?

刚写Google为我们提供的@AutoService,该注解可以方便的生成 META-INF/services/中注解的配置信息。

首先需要添加依赖:

compile 'com.google.auto.service:auto-service:1.0-rc2'

接起来在你的注解处理器类上使用@AutoService注解即可,如:


@AutoService(PrintProcessor.class)
public class PrintProcessor extends AbstractProcessor {

    //...省略相关代码
}

使用非常简单不是么,无需再关注 META-INF/services/的创建以注解处理器的注册了,简直棒呆了。关于该注解更多的信息请查看github:https://github.com/google/auto/tree/master/service


如何调试注解处理器

对于编译时注解处理器的调试显得略微麻烦些,不同构建方式(Maven,Ant,Gradle等)会稍微有些区别,但也只是形势上的区别,本质上还是离不开JPDA。

编译时注解处理器是运行在一个单独的JVM当中,因此我们想要对它进行调试可以使用Remote Debug。无论是是Eclipse中还是,IDEA当中,对Remote Debug功能都提供了良好的支持,作为IDEA二次开发出的Android Studio同样也不例外。先来看一下如何开启JVM的远程调试功能,在启动JVM的时候加上以下参数即可:

//jdk 1.5以前写法,当然该命令是先后兼容的
-J-Xdebug -J-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005

//jdk 1.5及以后版本写法
-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005

这些参数的含义这里不错细说,你唯一要做的就是修改address指定一个端口号。现在我们以Android Studio中调试注解处理器为例。

首先在gradle.properties中配置一下参数:

org.gradle.daemon=true
org.gradle.jvmargs=-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005

接下来在控制台当中使用gradle --daemon命令来启动守护线程.

到现在为止在注解处理器工程中的配置已经完成了。

接下来就需要在Android Studio中建立Remote Debugger,操作步骤如下:


这里写图片描述

这里的端口号要保持一致,不然Remote Debugger是连不上gradle的守护线程的.设置完成后该Remote Debugger就可以成功的链接到deamon线程了.

准备工作完成,下面就可以来调试了(别忘记加断点)。具体怎么做呢?很简单,就是重新编译即可。这里为了方便演示,直接图形化操作:


这里写图片描述

在构建过程中,Remote Debugger将会触发断点并挂起构建过程,接下来就可以像往常一样调试了.

关于注解处理的调试就到这里,其他工具大同小议,在这里就不做说明了。


总结

有关注解开发,调试方面的问题我们已经说的差不多了。在这2016年的最后一天,我们来年再见。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,542评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,596评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,021评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,682评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,792评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,985评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,107评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,845评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,299评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,612评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,747评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,441评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,072评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,828评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,069评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,545评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,658评论 2 350

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,846评论 25 707
  • 编译时注解处理 若希望对编译时的注解进行处理需要做 自定义类集成自AbstractProcessor 重写其中的p...
    生活理当如此阅读 8,847评论 3 18
  • 前面写了Android 开发:由模块化到组件化(一),很多小伙伴来问怎么没有Demo啊?之所以没有立刻放demo的...
    涅槃1992阅读 8,016评论 4 37
  • Spring Boot 参考指南 介绍 转载自:https://www.gitbook.com/book/qbgb...
    毛宇鹏阅读 46,778评论 6 342
  • 文 | 二静 图 | 网络 独行烟柳路, 月伴醉人归。 忽逢潇雨落, 梦忆把春追。 我是二静,愿你在每个22:2...
    二静不二阅读 842评论 1 3