小编说:依赖管理是Gradle 最耀眼的特点之一。
最佳情况下,你需要做的仅仅是在构建文件中添加一行代码,Gradle 将会从远程仓库下载依赖,确保你的项目能够使用依赖中的类。Gradle 甚至可以做得更多。如果你的项目中有一个依赖,并且其有自己的依赖,那么Gradle 将会处理并解决这些问题。这些依赖中的依赖,被称之为传递依赖。 本文选自《Gradle for Android 中文版》,介绍依赖管理的概念,并介绍添加依赖到Android项目的多种方式。
- 依赖仓库
当我们在讨论依赖时,通常指的是外部依赖,例如其他开发者提供的依赖库。手动管理依赖会是一个大麻烦。你必须找到该依赖,下载JAR文件,将其拷贝到项目,引用它。通常这些JAR 文件在它们的名称中没有版本号,所以你需要添加JAR的版本,以便知道什么时候更新。你还需要确保依赖库中存储在了源代码管理系统,以便团队成员在没有手动下载这些依赖时,也可以使用基于依赖的代码。
使用依赖仓库可以解决这些问题。一个依赖仓库可以被看作是文件的集合。Gradle默认情况下没有为你的项目定义任何依赖仓库,所以你需要在repositories代码块中添加它们。如果使用Android Studio,那么它会为你自动完成。repositories代码块,如下所示:
代码语言:javascript复制repositories {
jcenter()
}
- 本地依赖
在某些情况下,你可能仍然需要手动下载JAR 文件或原生库。你可能想创建自己的依赖库,这样你就可以在没有将其发布到公有或私有仓库时在多个项目中复用。在这种情况下,你不能使用任何在线资源,而是必须通过其他方式来添加依赖。下面将介绍如何使用文件依赖、如何引入原生依赖,以及在项目中如何引入依赖项目。
1 文件依赖
你可以使用Gradle 提供的files 方法来添加JAR 文件作为一个依赖,如下所示:
代码语言:javascript复制dependencies {
当你有很多JAR 文件时,这种方式会变得异常烦琐,一次添加一个完整的文件夹可能会更容易些:
代码语言:javascript复制dependencies {
默认情况下,新建的Android 项目会有一个libs 文件夹,其会被声明为依赖使用的文件夹。一个过滤器可以保证只有JAR 文件会被依赖,而不是简单地依赖文件夹中的所有文件:
代码语言:javascript复制dependencies {
这意味着所有由Android Studio 创建的Android 项目,你都可以将JAR 文件放置在libs 文件夹中,其会自动包含在构建路径和最终的APK 中。
2 原生依赖库
用C 或C 编写的依赖库可以被编译为特定平台的原生代码。这些依赖库通常包含几个.so 文件,可用于所有平台。Android 插件默认支持原生依赖库,你所需要做的就是在模块层创建一个jniLibs 文件夹,然后为每个平台创建子文件夹,将.so 文件放在适当的文件夹中。
如果此约定不生效,那么你可以在构建文件中设置相关位置:
代码语言:javascript复制android {
sourceSets.main {
jniLibs.srcDir 'src/main/libs'
}
}
3 依赖项目
如果想分享一个使用Android APIs 或Android 资源的依赖库,那么你需要创建一个依赖项目。依赖项目通常和应用项目类似。你可以使用相同的任务来构建和测试依赖项目,并且它们可以有不同的构建variants。不同之处在于输出。应用项目将生成一个可被安装和运行在Android 设备上的APK,依赖项目则生成一个.aar 文件。该文件可被Android 应用项目用作依赖库。
① 创建和使用依赖项目模块
不同于应用Android 应用插件,构建脚本需要应用Android 依赖库插件:
代码语言:javascript复制apply plugin: 'com.android.library'
在应用中包含依赖项目的方式有两种。一种是在项目中当作一个模块,另一种是创建一个可在多个应用中复用的.aar 文件。
如果在项目中创建了一个模块作为依赖项目,那么你需要在settings.gradle 中添加该模块,在应用模块中将它作为依赖:
代码语言:javascript复制Include ':app', ':library'
在这种情况下,依赖模块被称之为依赖库,并且文件夹的名称与此相同。为了在Android模块中使用依赖库,你需要在Android 模块的build.gradle 文件中添加一个依赖库:
代码语言:javascript复制dependencies {
其会在应用模块的类路径中包含依赖库的输出。
②使用.aar 文件
如果你创建了一个依赖库,并且想在不同的Android 应用中复用,那么你可以创建一个.aar 文件,然后将其作为一个依赖添加到你的项目中。在构建依赖库时,模块目录下的build/output/aar/ 文件夹将会生成.aar 文件。为了添加一个.aar 文件作为依赖,你需要在应用模块中创建一个文件夹,复制.aar 文件至该文件夹,并添加该文件夹作为依赖仓库:
代码语言:javascript复制repositories {
这使得我们可以填加任何文件到该目录下,并将其作为依赖,具体操作方法如下:
代码语言:javascript复制dependencies {
其告知Gradle 查找具有特定名称且扩展名为.aar 的依赖库。
- 依赖概念
这里有几个依赖相关的概念理解起来非常有意思(即便现在用不到它们),其中之一就是配置的概念,其解释了贯穿整章用作依赖的compile 关键字。
1 配置
有时可能你不得不和一个只在特定设备上工作的SDK 打交道,比如特定厂商的蓝牙SDK。为了能够编译该代码,你需要将SDK 添加至编译类路径。你并不需要添加SDK 到你的APK 中,因为其早已存在于设备中。这就是所谓的依赖配置。
Gradle 将多个依赖添加至配置,并将其命名为集文件。下面是一个Android 应用或依赖库的标准配置:
- compile
- apk
- provided
- testCompile
- androidTestCompile
compile 是默认的配置,在编译主应用时包含所有的依赖。该配置不仅会将依赖添加至类路径,还会生成对应的APK。
如果依赖使用apk 配置,则该依赖只会被打包到APK,而不会添加到编译类路径。provided 配置则完全相反,其依赖不会被打包进APK。这两个配置只适用于JAR 依赖。如果试图在依赖项目中添加它们,那么将会导致错误。
最后,testCompile 和androidTestCompile 配置会添加用于测试的额外依赖库。在运行测试相关的任务时,这些配置会被使用,并且在添加如JUnit 或Espresso 测试框架时,特别有用。如果你只希望在测试APK 时使用这些框架,那么就不会生产APK。
除了这些标准配置外,Android 插件还针对每个构建variant 都生成了一份配置,使其添加依赖配置化成为可能,例如debugCompile、releaseProvided 等。当你只想在debug 构建中添加logging 框架时,这会非常有用。
2 语义化版本
版本化是依赖管理的重要部分。将依赖添加到JCenter 等依赖仓库时,约定遵循了一套版本化规则,我们称之为语义化版本。在语义化版本中,版本数字的格式一般为major.minor.patch,数字则按照下列规则依次增加:
- 当做不兼容的API 变化时,major 版本增加。
- 当以向后兼容的方式添加功能时,minor 版本增加。
- 当修复一些bug 时,patch 版本增加。
3 动态化版本
在某些情况下,你可能希望在每次构建你的应用或依赖库时,都能够获取到最新的依赖。
要想做到这一点,最好的实现方式是使用动态化版本。动态化版本的使用方式有很多种,例如:
代码语言:javascript复制dependencies {
第一行,我们告知Gradle 获取最新的patch 版本。第二行,我们希望能获取每一个最新的minor 版本,且minor 版本至少是2。最后一行,我们告知Gradle 获取依赖库的最新版本。
在使用动态化版本时,需要格外小心。如果你允许Gradle 获取最新版本,则很可能Gradle 获取的依赖版本并不稳定,它会导致构建中断。更糟糕的是,其会导致在构建服务器上和你自己的机器上运行着不同版本的依赖,从而导致应用程序的行为不一致。
当你试图在构建文件中使用动态化版本时,Android Studio 将会警告你可能存在的问题,如图所示。
- Android Studio
添加新依赖的最简单的方式是使用Android Studio 的 Project Structure 对话框。从File 菜单栏打开对话框,导航到Dependencies,获取当前依赖概要,如图。
在该对话框中,你可以通过单击绿色加号图标来添加新的依赖。你可以添加其他模块和文件,甚至可以通过JCenter 搜索相关依赖。
在项目中使用Android Studio 对话框,不仅能够轻松获取依赖概要,添加新的依赖库,而且无须在build.gradle 文件中手动添加代码,即可直接通过IDE 搜索JCenter。
- 总结
本文我们研究了添加依赖到Android 项目的多种方式,学习了所有形式的依赖仓库,以及在未使用依赖仓库时,如何依赖文件。还介绍了关于依赖的一些重要概念:配置名称、语义化版本、动态化版本。前面我们多次提到过构建variants,我们会在《Gradle for Android 中文版》中解释什么是构建variants,为什么它们非常重要。构建variants 可以使开发、测试和分发应用变得更加容易。了解variants 工作原理可以显著提高开发和分发过程的速度。