第五章 管理多模块构建
Android Studio 不仅可以为 应用 和 依赖库 建立模块,还可以为 Android Wear、Android TV 和 Google App Engine 等创建模块,所有这些模块都可以在一个单一的项目中使用。
注: 一个模块和一个项目之间是有区别的,一个模块可以是一个 Android 应用也可以是一个 Google App Engine 的后端,而一个项目是模块的集合。
本章内容:
- 解剖多模块构建
- 为一个项目添加模块
- 提示和最佳实践
一、解刨多模块构建
通常,一个多模块项目有一个根目录,在其子文件夹中包含所有的模块。
需要在项目的根目录中提供一个 settings.gradle
文件来告知 Gradle 项目的结构以及哪些文件夹包含哪些模块。
以下是多模块项目的结构图:
<div align=center>
<div align=left>
这是最简单最直接的方式。在项目的
settings.gradle
文件中声明了所有的模块:
include ':app', ':library'
该代码确保了 app 和 library 模块包含在构建配置中。我们需要做的就是添加模块的目录名。
如果想给 app 模块添加 library 模块作为一个依赖,那么你需要将它添加到 app 模块的 build.gradle
文件中:
dependencies{
//在一个模块中添加依赖
//使用带有模块路径作为参数的 project() 方法
implementation project(':library')
}
如果想使用子文件夹来管理模块,则目录结构如图所示:
<div align=center>
<div align=left>
现在该项目有两个不同的 library,并且这些 library 模块不在项目的根目录下,而是位于一个特定的 library 目录,基于这个目录结构,可以在 settings.gradle
中如下声明:
//冒号表示路径描述中的斜线
//所有的路径都是相对于根目录的 settings.gradle 文件的位置
include ':app", ':libraries:library1', ':libraries:library2'
在子目录中添加一个模块作为另一个模块的依赖(library1/library2 作为 app 的依赖),要从根目录引用它 ( ':' 相对 settings.gradle 文件的位置,也就表示了根目录),在 app 中依赖 library1:
dependencies{
implementation project(':libraries"library1')
}
1. 重访构建生命周期
构建过程的初始化阶段:
<div align=center>
<div align=left>
配置多模块项目的构建策略有以下三种:
- 在根目录的
build.gradle
文件中配置所有模块的设置 - 每个模块都有一个独立的
build.gradle
- 将每个模块共性的配置,在根目录的
build.gradle
中设置,每个模块的独有的配置在模块自己的build.gradle
中配置
因为第一、第二种各有优缺点,Android Studio 遵循了第三种策略。
2. 模块任务
当我们在项目根目录下的命令行界面运行一个任务时,Gradle 会找出哪个模块有这一名称的任务,然后为每个模块执行该任务。
注: 在哪个模块的目录下执行 gradlew assembleDebug
就会有构建哪个模块的 debug 版本。在根目录下执行,则会构建全部模块。
注: 若不想来回切换模块目录,可以在任务名称之前加上模块名,来指定在特定的模块上运行该 task 。 eg:gradlew :wear:assembleDebug
只会构建 wear
模块的 debug 版本。
二、将模块添加到项目
添加模块很简单,使用 AS 的向导即可完成,但是要注意的是,添加模块的时候有可能会导致 app 模块的构建文件被改变,因为 IDE 以为你添加了新模块是要在 app 模块中使用,所以可能会在 app 模块的构建文件中添加一行用于引用 新模块 的代码。
1. 添加一个 Java 依赖库
<div align=center>
image<div align=left>
生成的 build.gradle
如下所示:
apply plugin: 'java-library'
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
}
//指定编译 .java 文件的 jdk 版本
sourceCompatibility = "7"
//确保生成的字节码文件与 此处指定版本(或更高版本)的 java虚拟机 兼容
targetCompatibility = "7"
因为 Java 依赖库模块使用的是 Java 插件,而不是我们之前看到的 Android 插件,所以许多 Android 特定属性和任务都不能使用。在 Java 依赖库中也不需要使用到 Android 特定的内容。
可以正常的向 libs
目录中添加 JAR包
,若想在 app 模块中依赖新建的 Java 模块,需要在 app 的 build.gradle 文件中使用 project() 方法指定依赖项.
<div align=center>
image<div align=left>
implementation project(':javalib')
注: app模块 依赖于 javalib模块,则在构建项目时,javalib模块 总会在 app 之前构建。
2. 添加一个 Android 依赖库
<div align=center>
image<div align=left>
将 Android依赖库加入到 app模块中:
implementation project(':androidlib')
一个 Android依赖库 不仅包含其中的 java代码,还包含所有的 Android资源:manifest
strings
layouts
等。一旦你的 app 中依赖了一个 Android依赖库,那么你就可以在该 app 中使用 依赖库 的所有类和资源。
3. 使用 Google App Engine
Google App Engine
是一个云计算平台。可以使用托管的 Web
应用,而无须建立自己的服务器。
使用 Google App Engine
的 Cloud Endpoints
可以很容易地为我们的应用创建后端。
AS 3.0 已经不支持直接创建 Google App Engine
模块。
而且现在 Android 与其后端也是分离的,所以就不研究 Google App Engine
了。
三、一些提示
1. 在 Android Studio 中运行模块任务
可以在 AS 的 Gradle
工具窗口查看或执行任务,也可以选择命令行。
2. 加速多模块构建
当构建一个多模块项目时,Gradle 会按顺序处理所有的模块。我们可以通过并行运行所有模块来使得构建过程更快。此功能已存在于 Gradle 中,但默认不开启。
在项目根目录的 gradle.properties
属性文件行中配置 parallel
属性:
//开启并行构建
org.gradle.parallel=true
Gradle 会基于可用的 CPU内核 ,来选择正确的线程数量。为了防止出现同一模块同时执行两个任务的问题,每个线程只拥有一个完整的模块。(可用理解为,构建是并行的,模块是同步的)
必要条件: 若想使用并行构建,模块之间必须是分离的。
3. 模块耦合
通过在 build.gradle
文件中使用 allprojects
,我们可以在一个项目中定义所有模块的属性。
当你的项目有多个模块时,你可以在任何模块中使用 allprojects
来应用属性到项目的所有模块中。
Gradle
甚至允许一个模块引用另一个模块的属性。(此时两模块是耦合的)
只要两个模块互相访问了对方的任务或属性,就认为这两个模块是耦合的,耦合会造成几个后果:
- 放弃了可移植性
- 无法使用并行构建
可以使用根模块作为媒介,让模块只与根模块耦合,而不是和其他模块耦合。
四、总结
学到了多模块构建的结构以及模块之间如何依赖。
下一章:测试
网友评论