Gradle 介绍及解惑

个人笔记整理系列,本文整理自张哥 QQ 聊天群 (2016-6-24)

Gradle 是什么?

简单来说,Gradle 是一种构建系统,但是什么是构建系统呢?

当我们使用 Android Studio,写完代码,编译、运行、生成 apk 包并且安装到手机上,这一系列过程都可以算是 Android 应用程序构建的一部分。在 Gradle 之前,Google 开发了 ADT (Android Development Tools) 用于构建 Android 应用程序,而 AS 正式版的问世之后,这个构建的工作就交给 Gradle 来做了。Gradle 由开源社区维护,使用起来简洁高效,所以谷歌把它作为 AS 的默认构建工具。

有了 Gradle 之后,即使不使用 IDE,而是在 EditPlus、Sublime Text 这样的编辑器上写代码,我们依旧可以通过简单的 Gradle 命令,将程序编译、打包、运行,只不过没有那么多的智能提示、智能跳转而已。

Gradle 最令人称道的部分其实不仅仅是编译、运行、打包的高效上,还有便捷的依赖管理。举个例子:最早期开发时引用第三方库大都是下载 jar 包,然后拷贝到 libs 文件夹下。这种方式管理起来很麻烦,很混乱,比如 jar 包升级了,那么我们又得重新下载,重新拷贝过来并替换。用了 Gradle 之后,只需要一行简单的代码:

1
implementation 'androidx.xxx:version_name'

类似这样的依赖方式,既方便又直观,升级的话直接改下版本号就可以了。

关于 Gradle 的常见疑问

Q:Gradle 是专门针对 Android 开发使用的吗?

A:Gradle 是一个基于 Groovy 语言的构建工具。它是可以单独存在的,跟平台无关,也跟 IDE 无关。


Q:AS 一推出就默认集成了 Gradle 构建工具,抛弃了原来的 ADT。怎么集成的呢?

A:Google 为了让 Android 支持 Gradle 构建,单独开发了 Android Gradle Plugin,当我们创建 Android 的 Gradle 项目时都需要使用到这个 Gradle 插件。打开项目根目录的 build.gradle,buildscript 中的 dependencies 代码块中有这样一行代码:

1
classpath 'com.android.tools.build:gradle:version_name'

这个就是 Gradle 插件的依赖,后面的版本号代表的是这个 Android Gradle Plugin 的版本。

查看 Android Gradle Plugin 的版本更新以及 Release Note

查看 Gradle 的版本更新以及 Release Note


Q:如何查看当前 android gradle 插件版本对应的 gradle 版本?

A:首先确保启用了 gradle wrapper,在 AS 的设置中找到 Build - Gradle,然后在 Project Level Settings 中选择Use default gradle wrapper (recommanded)。然后在项目根目录下,输入 ./gradllew -v,就可以看到当前的 gradle 版本(首次输入会下载 Gradle)。


Q:为什么输入的命令是 gradlew 而不是 gradle ?

A:gradlew 是 gradle wrapper 的缩写,顾名思义,它是 gradle 的一层包装,方便兼容不同版本的 gradle。比如我们有多个项目,每个项目依赖的 gradle 版本不同,为了让每个项目都能成功构建,我们就需要使用 gradle wrapper,它相当于在每个 Android 项目里都内置了一个 gradle。

打开项目根目录可以看到有一个 gradle 文件夹,下面有个 wrapper 的文件夹,打开里面的 gradle-wrapper.properties 文件,可以看到如下内容:

1
2
3
4
5
6
7
8
9
10
11
\#Mon Dec 28 10:00:20 PST 20xx

distributionBase=GRADLE_USER_HOME

distributionPath=wrapper/dists

zipStoreBase=GRADLE_USER_HOME

zipStorePath=wrapper/dists

distributionUrl=https\://services.gradle.org/distributions/gradle-x.x-all.zip

这里其实就已经可以看到你当前项目依赖的 gradle 版本是多少了,跟你输入 ./gradlew -v 应该显示的是一个版本。如果你本地没有下载这个版本的 gradle,那么第一次运行项目时会自动先去下载 gradle。

下载后的位置在:

1
2
3
Windows: C:\Users\{user.name}\.gradle\wrapper\dists\

Mac: /Users/{user.name}/.gradle/wrapper/dists/

Q:为什么命令行下第一次输入 ./gradlew 命令要下载?AS 运行过不是说明已经下载了对应版本的 gradle 了吗?

A:这应该是个 bug。我猜测命令行下可能无法识别 AS 使用的 gradle 位置,所以又重新下载了一个,打开 /Users/{user.name}/.gradle/wrapper/dists/gradle_version,可以看到同一个 gradle 版本下有两个文件夹,说明下载了两次,一个是 AS 下载的,一个是通过命令行下载的。


Q:如何使用 AS 打开 Github 上的 Demo?

A:首先检查 gradlew wrapper,不同版本的 AS 支持的 gradle 版本也不同,比如 AS 1.0 的时候要求只能使用 gradle 1.x 的版本,等到 AS 2.0 推出后,开始不支持 gradle 1.x 的版本,会强制让你升级到 gradle 2.0 以上,AS 3.0 之后支持 gradle 4.0 及以上(同时开始支持 Java 8)。所以新项目还需要检查下 gradle wrapper 版本是不是很老旧了,一般与你本地的 gradle 版本保持一致就可以了。

我写了一个批量修改 gradle 版本的工具类,有需要的可以参考下。

常见问题解决方案

  1. 遇到 ./gradlew: Permission denied 怎么办?

    只要在项目根目录下执行 chmod +x gradlew 就可以了

常用命令

Gradle 命令 (Windows 上使用 gradlew) 解释
./gradlew clean 清除编译缓存,删除 build 文件夹
./gradlew tasks –all 查看所有任务
./gradlew :moduleName:taskName 执行对应 module 下的 task
./gradlew app:dependencies –configuration releaseRuntimeClasspath 查看编译时依赖库
./gradlew assembleRelease (gradlew aR) 编译并打 release 包
./gradlew assembleDebug (gradlew aD) 编译并打 debug 包(app/build/outputs/apk)
./gradlew aD –offline 编译打包时使用 offline 模式
./gradlew installDebug 安装 Debug 包
./gradlew -q dependencies app:dependencies compileReleaseSource 查看项目库的依赖树
./gradlew processDebugManifest –stacktrace 显示 Manifest 合并出错信息