Java 的注解处理器AnnotationProcessor 和 Kotlin的注解处理器 Kapt 会在编译期,根据代码的注解,生成代码。对处理注解的代码进行调试,可以更快的定位问题。那么就需要在编译期调试代码
网上很多文章,只是介绍了如何操作,但是没有说明原理的,导致不明所以,操作时候出现问题就不知从何下手
1、首先我们先对调试器进行一些简单的了解,再去介绍 调试注解处理器AnnotationProcessor就会清晰明了,懂了原理,操作基本就是一次学会。
2、Java和Kotlin 对注解的处理,使用的工具不一样。
所以他们debug调试的方法不太一样,后面会详细介绍
平时在使用AS debug APP的时候,调试器会自动attach到app的进程。
其实我们也可以手动把调试器attach到指定app的进程。
1、点击run 运行 项目,非debug
2、点击as中的attach debugger Android process 按钮
3、选择调试机中,当前项目的进程
这样就可以对进程调试了,调试过Android 源码的朋友应该对这个很熟悉。
注解处理器AnnotationProcessor,是在编译期执行的,那么如何把调试器attach到编译期间的进程上
答案就是通过远程调试,远程调试可以把调试器attach到任意时期的进程上
Gradle 是运行在JVM上的,在初始化的时候会加载一些必要的库,所以第一次运行会有些慢。为了避免每次运行都运行慢的问题,Gradle 推出了一个长时间存活的进程——Daemon (关于Gradle Daemon的官方文档)Gradle 调用AnnotationProcessor 是在Daemon 进程
下面以bufferknife为例,来演示如何调试注解处理器AnnotationProcessor
点击Run——>Edit configurations,会打开如下图的界面,点击“+”号,选择Remote
首先打开AS右边的Gradle小窗口,然后打开butterknife-integration-test->other目录,找到compileDebugJavaWithJavac,右键选择,如下图所示:
把在上面复制的命令粘贴到下图VM options的位置:
VM options 是配置Daemon 进程的VM 参数,
注意需要把server=n 改为 server=y,如下 这么做是为了保证compileDebugJavaWithJavac运行前会一直等待调试器的连接。
-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005
为什么要配置上面这两个东西呢?
这样当该任务执行的时候,就可以进行调试
在开始调试前,注意一定一定要清掉注解处理器生成的文件,在build文件夹里的文件。可以执行clean project来清理。
因为如果注解所在文件不发生任何改变的话,编译时注解处理器只会运行一遍。不清理再次执行,就直接build完成了
因为该任务运行在Daemon 进程 中,也对Daemon 进程配置了远程调试,所以执行该任务(它是个调试任务),会等待远程调试器,所以debug远程调试器就可以断点了
选择已创建好的Remote调试——Annotation,启动调试
这时compileDebugJavaWithJavac,附加到远程调试器,开始正常执行,就会在代码指定断点处停下来
注意:之前提到过,AnnotationProcessor生成文件一次后,如果注解没有发生改变,接不会再次执行。所以再次调试的时候一定记得clean project
网上有一些是通过命令来实现这个功能,原理是一样的
在开始介绍方法前,先把原理梳理一下,那么后面操作就会一目了然
Kotlin代码处理注解,使用的是Kapt,而不是AnnotationProcessor
在使用Gradle构建工具,对kapt的处理,不是在Daemon 进程,而是在kotlin.daemon 进程中,所以需要对kotlin.daemon 的jvm参数进行配置,而不能像上面那样配置
和 2.1、创建远程调试 的方法一模一样
在添加 kapt.use.worker.api=true
到 Gradle properties
Since 1.3.20 kapt.use.worker.api runs annotation processing in the main Gradle process.
执行命令
gradlew --no-daemon -Dorg.gradle.debug=true -Dkotlin.daemon.jvm.options="-Xdebug,-Xrunjdwp:transport=dt_socket\,address=5005\,server=y\,suspend=n" :app:clean :app:assemble
参数解释:
--no-daemon
不使用daemon进程
-Dorg.gradle.debug=true
开启一个新的Gradle process,用于远程调试
-Dkotlin.daemon.jvm.options
对kotlin.daemon进程设置远程调试参数
命令中的\ ,千万不要去掉,否则调试不了
我后来又重新调试时
环境:
kotlin 1.3.31
android studio 3.6.1
gradle 4.10.3
com.android.tools.build:gradle:3.2.0
如果没有开启远程调试,执行的任务会卡住,此时开启远程调试,就可以继续运行。
这里延伸 一下,kapt是先生成stub (一个java类),然后根据生成的java类的注解,去生成代码 ,如下图
如果你的项目是java kotlin 混合的,以执行任务语言为主。
例如:
app 是java,lib 是kotlin,那么用java的注解调试方式,lib中的注解也是可以断点调试的
如果app,lib 都是kotlin,则只能使用kotlin的注解调试方式
参考:
如何调试编译时注解处理器AnnotationProcessor
编译时注解处理方
Annotation Processor
调试Annotation Processor编译时注解器
如何debug自定义AbstractProcessor
Android APT 编译期进入debug模式
Annotation Processing with Kapt and Gradle
Debug Annotation Processor Kapt
Can’t Debug an Annotation Processor when using kapt and gradle
Android Studio中kapt调试annotation processor的一些注意事项
该文章的内容,我之前调试时有这样的情况,需要在执行某个任务,快速启动远程调试,但是后来并没有这样的问题
Annotation Processing with Kapt and Gradle
Debug annotation processor in Kotlin