服务端相关 / Gradle Wrapper 详解

Gradle Wrapper 详解

前面一小节《Android项目Gradle配置详解》中我们介绍了 Android 项目的目录及 Gradle 配置,我们提到有个目录是/gradle/wrapper。今天这篇文章我们来学习 Gradle Wrapper。通过这篇文章我们将了解什么是 Gradle Wrapper?为什么需要用 Gradle Wrapper?以及 Gradle Wrapper 的重要性。

1. 什么是 Gradle Wrapper?

关于“什么是 Gradle Wrapper?”这个问题在官网是这么定义的:

The recommended way to execute any Gradle build is with the help of the Gradle Wrapper (in short just “Wrapper”). The Wrapper is a script that invokes a declared version of Gradle, downloading it beforehand if necessary. As a result, developers can get up and running with a Gradle project quickly without having to follow manual installation processes saving your company time and money.—官方

我们翻译过来大致意思就是:官方建议任何 Gradle 构建方法在 Gradle Wrapper 帮助下运行。Gradle Wrapper 它是一个脚本,调用了已经声明的 Gradle 版本,并且我们编译时需要事先下载它。所以,开发者能够快速的启动并且运行 Gradle 项目,不用再手动安装,从而节省了时间成本。

我们可以称 Gradle Wrapper 为 Gradle 包装器,是将 Gradle 再次包装。让所有的 Gradle 构建方法在 Gradle 包装器的帮助下运行。

2. 为什么需要 Gradle Wrapper?

其实关于这个问题在介绍 Gradle Wrapper 的时候已经回答了。下面我们通过一个开发生活中的案例来形象的介绍一下。我们日常开发中肯定都是一个团队在开发,如果没有 Gradle Wrapper 的话,那么团队中每来一个新同事,就需要在电脑中安装 Gradle 环境。但是有时候我们不同项目 Gradle 的版本又是不一样的,这就为我们的开发工作带来了不便。

于是乎 Gradle 就提供了 Gradle Wrapper,可以让我们的电脑中不安装 Gradle 环境也可以运行 Gradle 项目。这就是上面官方介绍中所说的 Gradle 是一个脚本,调用事先声明的 Gradle 版本,编译前去下载它,这样我们的电脑中就不用再去手动安装 Gradle 环境了,从而间接的提高了我们的开发效率。

从前面一节课我们可以看到 AndroidStudio 创建项目时默认会创建 Gradle Wrapper 目录,这也就是我们不用去手动安装 Gradle 环境的原因。Gradle Wrapper 的工作流程图如下:

图片描述
它的流程主要分为 3 步走:

首先当我们刚创建的时候,如果指定的版本没有被下载,就先会去 Gradle 的服务器中下载对应版本的压缩包,下载完成后需要先进行解压缩并且执行批处理文件,后续项目每次构建都会重用这个解压过的 Gradle 版本。

3. 如何构建 Gradle Wrapper?

要想构建 Gradle Wrapper 就必须本地先配置了 Gradle 环境变量,具体的配置方法可以参考《构建自己的 Gradle 工程》中关于 Gradle 环境变量的配置。Gradle 的命令中已经内置了 wrapper 命令,其实就是执行 warpper 任务。该任务就是生成我们前面说的 gradle 文件夹及它的子目录 wrapper 文件夹。在根目录下我们先删掉 gradle 文件夹,然后在项目根目录执行gradle wrapper命令。

C:\Users\LeiQi PC\Documents\MyApplication>gradle wrapper

Deprecated Gradle features were used in this build, making it incompatible with Gradle 7.0.
Use '--warning-mode all' to show the individual deprecation warnings.
See https://docs.gradle.org/6.0.1/userguide/command_line_interface.html#sec:command_line_warnings

BUILD SUCCESSFUL in 1s
1 actionable task: 1 executed

我们会看到会重新生成 Gradle 文件夹,目录结构如我们上节中的一样如下。

图片描述
这两个文件的含义如下:

  • gradle-wrapper.jar: 既然是 jar 包,那么它肯定是包含了 Gradle 运行时的逻辑代码;
  • gradle-wrapper.properties: 这个文件主要负责配置 Gradle wrapper 运行时的属性文件,声明具体使用哪个版本的 Gradle。

4. 配置 Gradle Wrapper

我们上面说gradle-wrapper.properties文件指明了 Gradle 的版本号,和 Gradle 运行时的行为属性文件。下面我们具体看下这个文件的内容:

distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.0.1-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

关于每个字段的意思如下:

  1. distributionBase: Gradle 解包后存储的父目录;
  2. distributionPath: distributionBase指定目录的子目录。distributionBase+distributionPath就是 Gradle 解包后的存放的具体目录;
  3. distributionUrl: Gradle 指定版本的压缩包下载地址;
  4. zipStoreBase: Gradle 压缩包下载后存储父目录;
  5. zipStorePath: zipStoreBase指定目录的子目录。zipStoreBase+zipStorePath就是 Gradle 压缩包的存放位置。

Tips: 这里我们需要关注 distributionUrl 这个字段,我们经常会遇到升级 AndroidStudio 后项目初始化编译缓慢的问题。这个问题就是升级后 AndroidStudio 会自定改掉gradle-wrapper.properties里面 distributionUrl 字段 Gradle 的版本号。遇到这个问题我们不慌,可以将该字段改为我们本地已经下载好的版本号。修改完成后重启 AndroidStudio 就可以很快编译通过了。

5. 使用 Gradle Wrapper 下载 Gradle

使用 Gradle wrapper 下载 Gradle 我们可以点击 AS 界面上的同步按钮,也可以使用 gradlew 命令来执行 gradle 命令来下载,下面以 Windows 系统为例,我本地distributionUrl配置的 Gradle 版本是gradle-6.0.1-bin.zip,我们现在改为gradle-5.0-all.zip版本,执行clean命令,看看有没有下载 5.0 版本下载:

C:\Users\LeiQi PC\Documents\MyApplication>gradlew clean
Downloading https://services.gradle.org/distributions/gradle-5.0-all.zip
............10%............20%.............30%............40%............50%.............60%............70%.............80%............90%............100%

Welcome to Gradle 5.0!

BUILD SUCCESSFUL in 1s
2 actionable tasks: 2 up-to-date

我们看到这里已经下载了 gradle 5.0 版本,那么按照前面所说,再次执行命令,直接调用本地的 Gradle,不会去下载我们来看下:

C:\Users\LeiQi PC\Documents\MyApplication>gradlew clean

Deprecated Gradle features were used in this build, making it incompatible with Gradle 7.0.
Use '--warning-mode all' to show the individual deprecation warnings.
See https://docs.gradle.org/5.0/userguide/command_line_interface.html#sec:command_line_warnings

BUILD SUCCESSFUL in 1s
2 actionable tasks: 2 up-to-date

我们看到这里没有再去下载 Gradle 版本了而是直接使用上次下载的缓存下来的。

6. 升级Gradle Wrapper

升级 Gradle Wrapper 有 2 种方式:

  1. 一种是我们前面演示的,直接修改distributionUrl字段,然后执行Gradle 命令或是点击同步按钮同步。
  2. 还有一种就是执行 gradlew 命令gradlew wrapper –-gradle-version [version]这里我们将 5.0 升级为最新版 6.0.1.
C:\Users\LeiQi PC\Documents\MyApplication>gradlew wrapper --gradle-version 6.0.1

Deprecated Gradle features were used in this build, making it incompatible with Gradle 7.0.
Use '--warning-mode all' to show the individual deprecation warnings.
See https://docs.gradle.org/6.0.1/userguide/command_line_interface.html#sec:command_line_warnings

BUILD SUCCESSFUL in 1s
1 actionable task: 1 up-to-date

然后我们使用gradlew -v查看当前的 Gradle 版本号:

C:\Users\LeiQi PC\Documents\MyApplication>gradlew -v

------------------------------------------------------------
Gradle 6.0.1
------------------------------------------------------------

Build time:   2019-11-18 20:25:01 UTC
Revision:     fad121066a68c4701acd362daf4287a7c309a0f5

Kotlin:       1.3.50
Groovy:       2.5.8
Ant:          Apache Ant(TM) version 1.10.7 compiled on September 1 2019
JVM:          1.8.0_221 (Oracle Corporation 25.221-b11)
OS:           Windows 10 10.0 amd64

我们看到此时版本号已经升级为 6.0.1了。

7. 自定义 Gradle Wrapper

AndroidStudio 中 Gradle 内置了 Wrapper 任务,因此我们可以直接执行 Gradle wrapper。既然他是一个任务,那么我们其实也可以自定义这个任务,定义该任务我们可以指定上面gradle-wrapper.properties文件中的字段,如下所示:

task wrapper(type: Wrapper) {
    gradleVersion = '6.0.1'
    distributionUrl = '../../gradle-6.0.1-bin.zip'
    distributionPath=wrapper/dists
}

Tips: 这里自定义 wrapper 时,我们可以将distributionUrl字段指定为本地的目录。

8. 小结

这篇文章我们学习了 Gradle Wrapper,已经它的重要性和一些基本的操作。关于这个平时我们基本上用不到,所以只需要理解其原理就行了,唯一要注意的就是我们升级 AndroidStudio 后,项目第一次打开初始化编译换慢,这时候是因为系统更改了 gradle wrapper 中的 Gradle 版本,由于 Gradle 服务器在国外国内访问受限,所以我们可以将 Gradle 版本修改为之前本地下载过的版本号,然后重启 APP 就好了。