做 Android 开发必定会依赖第三方库,比如常用的如网络请求框架 OkHttp
、图片加载框架 Glide
等,即使你完全采用原生 API 来开发,也会依赖 AppCompat
或者 Support
之类的官方库。
以前 Android 开发是在『Eclipse』上进行的,开发者使用第三方库往往需要手动下载 Jar 包再到『Eclipse』内引用,在『Android Studio』推出后,得益于 Gradle 构建工具,我们只需在 Gradle 文件中用使用一行代码即可将第三方库从远程站点依赖到项目中,十分方便。
我们引用依赖一般都是使用 implementation
配置依赖项,的确大多数第三方库文档的 Usage 都是这么写的,大多数情况下我们这么用也没问题,但是我们依然需要了解其他的依赖项配置。
implementation
首先我们从最熟悉的 implementation
开始,为什么 implementation
是绝大多数第三方库文档所介绍的配置方式,同时也是『Android Studio』的默认配置方式?
原因其实很简单,与其他配置方式相比,此依赖项配置可以显著缩短构建时间,因为这样可以减少构建系统需要重新编译的 Module 数。
当 implementation
依赖项更改了其 API,Gradle 只会重新编译该依赖项以及直接依赖于它的 Module。同时,该 Module 在编译时不会将该依赖项泄露给其他 Module,也就是说,其他 Module 只有在运行时才能使用该依赖项。
api
当一个 Module 包含 api
依赖项时,该 Module 会以传递方式将该依赖项导出到其他 Module,以便这些 Module 在运行时和编译时都可以使用该依赖项。
此配置的行为类似于 compile
(现已弃用),会以传递方式导出到其他上游消费者。
其与 implementation
的最大区别在于能否被上游消费者调用,如下图所示:
假设 Module X 同时依赖 Library A 和 Library B,而 Library A 通过 implementation
引用 Library C,而 Library B 则使用 api
引用 Library D。
这时候,Module X 是不能够直接使用 Library C 的,但却能够直接使用 Library D。因为 implementation
可以让 Module 在编译时“隐藏”自己使用的依赖,而 api
则会“传递”自己的依赖。
同时,如果 api
依赖项更改了其外部 API,Gradle 会在编译时重新编译所有有权访问该依赖项的 Module,因此,拥有大量的 api
依赖项会显著增加构建时间。
除非要将依赖项的 API 公开给单独的 Module,否则应使用 implementation
依赖项。
compileOnly
Gradle 只会将依赖项添加到编译类路径,也就是说,不会将其添加到构建输出。
如果您创建 Module 时在编译期间需要相应依赖项,但它在运行时可有可无,此配置会很有用。
如果您使用 compileOnly
,那么您的 Module 必须包含一个运行时条件,用于检查是否提供了相应依赖项,然后适当地改变该 Module 的行为,以使该 Module 在未提供相应依赖项的情况下仍可正常运行。
这样做不会添加不重要的暂时依赖项,因而有助于减小最终 APK 的大小。此配置的行为类似于 provided
(现已弃用)。
runtimeOnly
Gradle 只会将依赖项添加到构建输出,以便在运行时使用。也就是说,不会将其添加到编译类路径。
此配置的行为类似于 apk
(现已弃用)。
annotationProcessor
我们在使用一些包含注解的第三方库时经常可以见到它,比如 Dagger
等。
如需添加对作为注解处理器的库的依赖,可以使用 annotationProcessor
配置将其添加到注解处理器的类路径。
使用此配置可以将编译类路径与注释处理器类路径分开,从而提高构建性能。
lintChecks
使用此配置可以添加您希望 Gradle 在构建项目时执行的 lint 检查。
需要注意,使用 Android Gradle Plugin 3.4.0 及更高版本时,此依赖项配置不再将 lint 检查打包在 AAR 项目中。
lintPublish
在 AAR 项目中使用此配置可以添加您希望 Gradle 编译成 lint.jar
文件并打包在 AAR 中的 lint 检查。这会使得使用 AAR 的项目也应用这些 lint 检查。
testImplementation
只在单元测试代码的编译以及最终打包测试 APK 时有效。
默认新建项目中 JUnit
就是以此配置依赖的,同时可以看到默认项目目录中除了我们一般写业务代码的 /src/main
目录外,还有 /src/test
目录供我们写本地单元测试,testImplementation
就可以为其 Source Set 添加依赖。
androidTestImplementation
只在单元测试代码的编译以及最终打包测试 APK 时有效。
默认新建项目中 Espresso
就是以此配置依赖的,同时可以看到默认项目目录中除了我们一般写业务代码的 /src/main
目录外,还有 /src/androidTest
目录供我们写仪器化单元测试、UI 测试等,androidTestImplementation
就可以为其 Source Set 添加依赖。
releaseImplementation / debugImplementation
仅仅针对 Release 或 Debug 模式的编译和最终的 Release / Debug Apk 打包。
DiDi 团队著名框架 DoKit
就是以此配置依赖的,可以针对 Release 和 Debug 采用不同的处理。
compile
该配置已弃用。
与 api
类似,Gradle 会将依赖项添加到编译类路径和构建输出,并将依赖项导出到其他 Module。
apk
该配置已弃用。
与 runtimeOnly
类似,Gradle 只会将依赖项添加到构建输出,以便在运行时使用,不会将其添加到编译类路径。
provided
该配置已弃用。
与 compileOnly
类似,Gradle 只会将依赖项添加到编译类路径,不会将其添加到构建输出。