Gradle笔记_5-管理多模块构建

Gradle笔记_5-管理多模块构建

5.1 解剖多模块构建

通常,一个多模块项目有一个根目录,在其子文件夹中包含所有的模块。

为了告知 Gradle 项目的结构以及哪个文件夹包含那些模块,需要在项目的根目录提供一个 settings.gradle 文件。

每个模块都可以提供自己的 build.gradle 文件。

下面是多模块项目结构:

多模块项目目录结构

在项目的 settings.gradle 文件中声明了所有的模块,如下所示:

include ':app', ':library'

该代码确保了 app 和 library 模块包含在构建配置中。

给 app 模块添加 library 模块作为一个依赖,需要在 app 模块的 build.gradle 文件中添加 library 依赖:

dependencies {
	implementation project(':library')
}

如果使用子文件夹管理你的模块,Gradle 也可以通过配置满足你的要求:

子文件夹管理模块

在 settings.gradle 中将模块添加到构建:

include ':libraries:library2'
include ':libraries:library1'
include ':library'
include ':app'

include ':app', ':library', ':libraries:library1', ':libraries:library2'

注意,在一个子目录中声明模块,所有的路径都是相对于根目录的(settings.gradle 文件所在目录)。冒号被用来替代路径中的斜线。

将一个子目录中的模块添加为依赖是,总是需要从根目录引用它。例如 app 模块需要依赖上面 libraries 下的 library1 模块,需要在 app 模块的 build.gradle 文件中添加:

dependencies {
    implementation project(path: ':libraries:library1')
    // 或 implementation project(':libraries:library1')
}

如果在子目录中声明了依赖,那么所有的路径都会相对于根目录。这样做的原因是 Gradle 是从项目的根目录开始创建项目依赖模型的。

5.1.1 重访构建生命周期

源码所述:

Project 和 build.gradle(Project#DEFAULT_BUILD_FILE)文件有一个一一对应关系,即每一个 build.gradle 文件对应一个 Project 对象。在构建的初始化阶段,Gradle 为每一个参与构建的工程(模块)组装一个 Project 对象,如下:

  • 为构建创建一个 org.gradle.api.initialization.Settings 实例。
  • 搜寻(源码用的 evaluate 评估) settings.gradle 脚本,如果存在,让 org.gradle.api.initialization.Settings 对象配置它。
  • 通过配置好的 org.gradle.api.initialization.Settings 对象创建 Project 实例(Project instances)层级结构。
  • 最后,针对每一个工程(模块)通过执行 build.gradle 文件为每一个 Project 评估。按广度评估,以便一个工程先于它的子工程被评估。

《Gradle for Android》书中所述:

  • 第一阶段,即初始化阶段,Gradle 搜寻 settings.gradle 文件。
  • 文件不存在,Gradle 则假设你只有一个单独的模块构建。
  • 有多个模块,根据 settings.gradle 文件中声明模块位置,Gradle 会处理各个模块的 build.gradle 文件,并把它们合并到构建进程模型。

Gradle 始终尝试从根目录找到依赖。

配置多模块项目构建策略的方式有以下几种:

  • 在项目根目录的 build.gradle 文件中配置所有模块的设置。
    简单,但会非常凌乱,特别当各个模块需要不同的插件,他们的插件又有其自己的 DSL 时。
  • 每一个模块都有一个独立的 build.gradle 文件。
    可确保模块不紧密耦合,也使得跟踪构建变化变得容易,因为你不需要找到哪些改变应用了哪些模块。
  • 混合做法。在项目的根目录的 build.gradle 中定义所有模块通用的属性,在每个模块的 build.gradle 中配置只针对该模块的设置。
5.1.2 模块任务

当你在项目根目录下的命令行界面运行一个任务时,Gradle 会找出哪个模块有着一名名称的任务,然后为每个模块执行该任务。

你可以:

  • 切换模块目录,运行 …/gradlew assembleDebug,【不成功】
  • 在任务名称之前加上模块名 $ gradlew :library:assembleDebug$ gradlew :libraries:library1:assembleDebug

5.2 将模块添加到项目

Android Studio 的 New Module 对话框:

Android Studio 的 New Module 对话框

5.2.1 添加一个 Java 依赖库

File > New > New Module > Select a Module Type 弹窗 > 选择 Java or Kotlin Library

添加一个新的 Java 依赖模块后,Android Studio 生成的 build.gradle 将如下所示:

// apply plugin: 'java'
plugins {
    id 'java-library'
}


java {
    sourceCompatibility = JavaVersion.VERSION_1_8
    targetCompatibility = JavaVersion.VERSION_1_8
}

dependencies {
    implementation fileTree(dir: 'libs', includes: ['*.jar'])
}

Java 依赖库模块使用的是 Java 插件,而不是之前的 Android 插件。
其构建文件也有基本的依赖管理设置,可以在 libs 文件夹添加 JAR 文件。依赖配置不依赖于 Android 插件。

例如添加一个名为 javalib 的 Java module 作为依赖库,在 settings.gradle 中,加上(通过 Android Studio 的 New Module 创建时,会自动添加):

include ':javalib'

给 app 模块添加 javalib 模块的依赖,只需要在构建文件中添加一行代码:

dependencies {
	implementation project(path: ':javalib')
}

该代码告诉 Gradle 在构建的时候引入一个名为 javalib 的模块。如果在你的 app 模块添加了该依赖,那么 javalib 模块将始终在构建 app 模块之前构建。

5.2.2 添加一个 Android 依赖库

File > New > New Module > Select a Module Type 弹窗 > 选择 Android Library

创建一个 Android 依赖库,默认 build.gradle 文件开始于下面这行代码:

apply plugin: 'com.android.library'
// 使用新版 Android Studio v4.1.2 如下
//plugins {
//   id 'com.android.library'
//}

添加 Android 依赖库依赖 给 app 模块,与添加 Java 依赖库方式完全相同:

dependencies {
	// implementation project(':androidlib')
	implementation project(path: ':androidlib')
}

一个 Android 依赖库不仅包含依赖库中的 Java 代码,还包含所有的 Android 资源,如 manifest、strings、drawables 和 layouts 等。一旦在你的 app 中引入了一个 Android 依赖库,那么你就可以在该 app 中使用依赖库的所有类和资源了。
执行构建任务组装 APK 时,会合并所有模块的资源。

融合 Android Wear

略过

适用 Google App Engine

略过

5.3 提示和最佳实践

5.3.1 在 Android Studio 中运行模块任务

你可以在 Android Studio 中直接运行 Gradle 任务。当有多个模块时,Android Studio 可以识别它们,并显示所有可用任务的分组情况。

Android Studio Gradle 可用任务的分组

Gradle 工具窗让运行模块特有的任务变得更加容易。同时针对所有模块运行一个任务,还是需要使用命令行,也更快些。

5.3.2 加速多模块构建

当创建一个多模块项目时,Gradle 会顺序处理所有的模块。我们可以通过并行运行所有模块来使得构建过程更快。
此功能在 Gradle 中默认不开启。需要在项目根目录的 gradle.properities 文件中配置 parallel 属性:

org.gradle.parallel=true

Gradle 会基于可用的 CPU 内核来选择正确的线程数。
注意:为了使冰箱工作有效,你需要确保你的模块之间是分离的。

5.3.3 模块耦合
  • 通过在 build.gradle 文件中使用 allprojects ,我们可以在一个项目中定义所有模块的属性。
  • 当你的项目有多个模块时,你可以在任何模块中使用 allprojects 来应用属性到项目的所有模块中。
  • Gradle 甚至允许一个模块引用另一个模块的属性。
    这些强大的功能,使得维护多模块构建更加方便。不足之处是模块耦合在一起了。

只要两个模块互相访问了对方的任务和属性,就认为这两个模块间是耦合的。耦合会造成几个后果

  • 放弃了可移植性。当需要提取一个模块,需要复制涉及的资源和设置,耦合越严重,提取越困难。
  • 对并行构建有影响。在任一模块中使用 allprojects,都将使得并行构建失效。

避免模块耦合:

  • 不直接从其他模块访问任务或属性来避免耦合。可以使用根模块作为中介,这样模块就只与根模块耦合而不是其他模块耦合。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值