我啥时候需要在 Gradle 依赖项中使用 Kapt?

Posted

技术标签:

【中文标题】我啥时候需要在 Gradle 依赖项中使用 Kapt?【英文标题】:When do I need to use Kapt in Gradle dependencies?我什么时候需要在 Gradle 依赖项中使用 Kapt? 【发布时间】:2019-11-03 14:46:44 【问题描述】:

我一直在 Gradle 中安装依赖项,但我不明白为什么有时我需要将 kapt 用于生命周期和房间数据库等库以使用 @Something 注释。但是在Retrofit2和Gson等一些库中,我不需要使用kapt,我可以使用@SerializedName等注解?

【问题讨论】:

【参考方案1】:

注解(例如@Something)基本上是代码的标签。您标记代码的一部分,以便一些其他代码可以找到这些标记。

这个“其他代码通常是一个注解处理器。它找到注释并使用标记有这些注释的代码执行某些操作。例如。它可以生成新代码(如 Dagger、Butterknife 等)。


取决于您在项目中引入依赖项的方式,(取决于您使用的keyword - implementationapicompileOnlyruntimeOnlyannotationProcessorkapt 等。 ),您的项目将使用不同的依赖项。

如果您使用annotationProcessor,您的依赖项将不会打包在您的应用程序中,但会在您的应用程序编译期间使用。

您不想在您的应用中打包编译器(处理@AnAnnotation 的代码),因为它只是用于正确准备您的应用的代码(并且从未在运行时的应用中使用)。

这样想:

如果您要上火车,并且需要打印火车票,您不想在火车上随身携带打印机。打印机打印完票后,你拿着票上火车。打印机已经完成了它的工作。你可以离开它。

如果您使用@AnAnnotation 标记某些代码,您只希望处理该注释的库完成其工作并消失。因此特殊类型的依赖 - annotationProcessor.

现在关于kapt。这很简单。如果您想在带有 Kotlin 代码的项目中使用注释处理器,只需使用 kapt 而不是 annotationProcessor。可以把它想象成 annotationProcessor 并支持 Kotlin。


一些库以不同的方式使用@Annotations。它们不会导致在编译时生成任何代码,但它们在运行时使用注释。

那些通常是基于反射的库,可在运行时“查看”代码。就像 Retrofit 在您的应用程序执行时查看您的 interface 一样。

这就是为什么您通常在您的应用程序中包含一个带有@Annotations 的库,并且这些注释被打包在您的 apk 中以进行运行时操作。


总结:

annotationProcessorkapt 关键字用于帮助您指定在项目中将如何使用依赖项。

如果您想引入一个使用注释并生成一些代码的库,请使用kapt,不要用已经完成工作且永远不会再次使用的代码“膨胀”您的 apk。

【讨论】:

@WayFaiGodfreyCheng 如果对您有帮助,请随时接受答案【参考方案2】:

通常,库通过以下两种方式之一与注解进行交互:

使用反射。库代码可以在运行时查询注释以执行某些逻辑。这些库通常会打包为单个工件,不需要使用kaptannotationProcessor。示例:Retrofit,它使用反射访问注释并且不包含注释处理器。 使用注释处理器。注释处理器是编译器插件,在主要编译步骤之前被调用,可以访问注释及其周围的代码,并根据此输入执行任务。注释处理器通常包含在单独的工件中,因为它们包含运行时不需要的代码,因此不应将其打包到您的 APK 中。示例:Butterknife,它在编译期间处理注释,并带有一个单独的 butterknife-compiler 模块,其中包含注释处理器。您应该使用butterknife-compiler 作为kaptannotationProcessor 依赖项,而不是implementationapicompile,因为在运行时不需要注释处理器。

要回答您的问题,没有通用方法可以知道依赖注释的库是否带有注释处理器。您应该查看特定库的文档并按照安装说明进行操作。

【讨论】:

以上是关于我啥时候需要在 Gradle 依赖项中使用 Kapt?的主要内容,如果未能解决你的问题,请参考以下文章

从 Gradle 依赖项中排除 .class 文件

如何从 Gradle 中的所有依赖项中忽略特定的传递依赖项

Android apk - 如何使用 gradle 从 3rd 方依赖项中排除 .so 文件

在 gradle 传递依赖项中检测 Apache Log4j 漏洞的存在

Android Studio - Gradle 实现 (...) exclude ... 不起作用(无法从依赖项中排除组)

如何从 Kotlin DSL build.gradle 中的所有依赖项中排除库?