最近在看 <<Think in Java >> 已经进展到注解一张, 其中讲解到了 APT(Annotation Process Tool) 的使用. 因为当时是基于 JDK1.5 的, 基于 com.sun.mirror.*
包下的相关类, 而这些类在 JDK1.8 的时候就已经完全废弃掉了, 替换成 javax.annotation.processing
和 javax.land.model
, 而且调试环境可以直接用 Android Studio. 所以, 就研究了下如使用新的 APT 工具.
知识准备
这个不是指导手册, 而是总结性的文章, 一些比较常用的操作和知识点就不展开. 愉快的阅读这篇博客之前, 可能需要了解:
- 注解的基本语法
- Android Studio 的常用操作
- gradle 的基本使用
不过我觉得对于一个合格的 Android 开发者, 这些应该没有问题吧. 还有, 小生的开发环境是 AS3.0, 在之前的版本会有些不同. 如果小伙伴们还是用的老版本的开发工具, 是时候升级了.
编码 & 问题 & 操作.
- 新建一个 Android Studio 工程.
介个 so easy 吧…
- 在项目中新建一个 Model, 暂且命名为
annotation
, 并且让我们的 app Model 去依赖这个库.
注意, 这个必须是一个 java library 而不能是 Android library, 如果是一个 Android library, 那么 javax.*
包中的一些东西就不能使用了.
- 在 java library 中创建一个注解类.
|
|
- 用该注解去修饰
MainActivity
中的方法.
|
|
- 在 java model 中创建一个类, 名字随意, 姑且命名为
MyProcessor
, 继承自AbstractProcessor
.
|
|
- 在 java Model 的 src/main 目录下创建
resources
包.
直接创建就可以, 不需要通过 Android Studio 的 Wizard.
在
resources
包中创建META-INFO
包, 接着在META-INFO
包中创建services
包.在
services
包中创建javax.annotation.processing.Processor
文件.在
javax.annotation.processing.Processor
文件中, 添加刚才创建的MyProcessor
的完整路径.
完整路径指的是相对路径, 对于当前测试项目而言, 为: com.congspark.annotation.MyProcessor
项目目录的最终的截图如下(请忽略这屎绿色的背景…):
前期的准备工作大致完成了, 现在我们向 MyProcessor
中添加写简单的功能, 仅仅是用来打印一些信息.
|
|
NOTE, getSupportedAnnotationTypes()
方法与类注解 @SupportedAnnotationTypes
的功能相同, 保留其中之一即可.
好了, 现在我们尝试着运行一下, 额, 不, 是编译一下程序. 使用 gradle 或者直接点击编译按钮都可以.
然而, 居然报错了… Gradle Console 的输出结果如下.
提示我们 Annotation processors must be explicitly declared now.
注解编译器必须明确的声明, 而且还给出了一个问题连接. 点击去看一下.
很是感动的说, 谷歌居然给出的是中文的, 不过, 这个翻译的… 其实就是让我们添加对 APT 插件的依赖. 跟着指导方案, 我们在 app 下的 build.gradle 文件中添加:
然后再次运行一下.
然后我们看到, 相应的方法名和相关信息, 同时上面的 :app:compileDebugJavaWithJavac
也证实了, 确实实在编译时运行的 MyProcessor
中的 process()
方法.
继续进阶
现在我们回到 <<Think in Java >> 中, 书中用的是 JDK1.5. 而现在的已经更新到 JDK1.8 了, 书中使用的 api 已经废弃不用了, 现在我们用新的 api 和 Android Studio, 重写调试一下. 实现的的功能为, 将 Multiplier
中的非静态的公共方法提取出来, 生成 IMultipler.java
的接口文件.
添加注解类.
|
|
具体的实体类. NOTE: 该实体类需要放在 app Model 中, 而不是 annotation Model 中, 否则无效.
|
|
然后是注解处理器.
|
|
编译一下, 然后就可以看到 IMultipler
接口了.
小小的总结一下, 这个仅仅是一个小小的示例, 算是辅助学习 <<Think in Java >> 吧. 项目中如果是生成 .java 文件, 可以考虑使用 JavaPoet 框架. 而且, 实际开发中, 应该引入访问者模式来解除耦合, 否则功能稍微多一点, 那么自己编写的注解处理器就会非常的复杂且难以维护.