Gradle 基础介绍
Gradle
本篇文章主要讲述 Gradle 的基本知识点,帮助大家了解 Gradle。
Gradle 背景知识
先介绍概念:
Gradle 是一个基于 Apache Ant 和 Apache Maven 概念的项目自动化建构工具。它使用一种基于 Groovy 的特定领域语言来声明项目设置,而不是传统的 XML 。
这个概念我们先不用去理解,只要知道 Gradle 是一个自动化构建工具就可以了。那么为什么我们在开发 Android 程序的时候需要去使用自动化构建工具呢?答案很简单,就是构建一个 Android 工程需要做很多重复性很高的事情,手动干这些事麻烦又浪费时间,所以我们选择让机器去做。好吧,我承认就是懒,聪明的开发者都愿意找一个正确,高效又能偷懒的方法。
Gradle 是 Google I/O 2013 大会上发布的,用来替换 Ant 和 Maven 的新工具,替换旧工具的原因当然是它们不能让开发者继续开心的懒下去了。
简单讲一下 Ant,Maven 和 Gradle 的关系,这是个题外话。Ant 可以自动化打包,但是许多东西要手动下载添加。Maven 既可以自动化打包,也能帮下载你需要的东西,但是它的逻辑策略写起来很麻烦。两个工具都不大好用,为了能开心的偷懒,Gradle 应运而生。Gradle 集成了上面的功能,非常方别开发使用,但由于某些网络问题,导致初学者使用起来体验并不好。
Gradle 文件结构
Android Studio 创建 Android 工程的时候会创建许多文件,这让不熟悉的人分不清楚不同文件的意义,这里我们先介绍一个最简单的 Gradle 结构,如下图。
这个结构一共有 5 个文件。其中 build.gradle 是我们需要编写的 Gradle 的脚本文件,另外四个文件组成了一个 Gradle 中的重要结构:Gradle Wrapper(Gradle 封装器)。
Gradle Wrapper
不同的开发者可能使用不同版本的 Gradle 来构建 Android 项目,多人开发的时候使用不同版本的构建工具,可能出现莫名其妙的问题。大家也都遇到过某个软件在这个电脑上没问题,在另外的电脑上有问题的情况吧。Gradle 封装器就是用来解决这个问题的,每一个封装器都绑定了一个特定版本的 Gradle,当你运行 Gradle 命令的时候,它会先下载相应的 Gradle 版本,并使用这个版本来执行构建,这样就避免了环境不统一的问题。这是个很棒的功能,但由于某些网络问题,下载会超时,导致了很多新手都栽在了这里。这里就不讲述怎么下 Gradle 了,网上很多这方面的资料。
为了完整起见,不要删除 Gradle 封装器里的文件或改变目录结构,这里介绍一下封装器里文件的功能
- gradlew (Unix Shell 脚本)
- gradlew.bat (Windows 批处理文件)
- gradle/wrapper/gradle-wrapper.jar (Jar 包)
- gradle/wrapper/gradle-wrapper.properties (封装器属性)
Gradle 版本会被下载到用户目录下的 .gradle/wrapper/dists 中。
查看 gradle-wrapper.properties 文件可以看到当前封装器使用的 gradle 版本号。
Unix Shell 环境下使用 gradlew 命令
Windows 环境下使用 gradlew.bat 命令
build.gradle
build.gradle 是构建所需要的脚本文件,这里给一个最简单的示例。
新建了一个名为 hello 的任务,输出 Hello World。
task hello {
println "Hello World!"
}
执行 gradlew.bat hello 就能看见 Hello World 输出在控制台上了。
Android Studio 里的 Gradle
这里新建一个空的工程,来介绍 Gradle 的作用。
工程目录
Android Studio 是按项目建立的,项目里面可以有不同的 app 模块,简单的说一个项目可以编出几个不同的 app 软件。
项目目录界面如下
下面介绍目录中 build.gradle 和 Gradle 封装器之外的部分。
- .gradle 文件夹下放的是 Gradle 构建时的记录信息,无需关心
- .idea 是 Android Studio 工程记录信息,无需关心
- app 存放对于的模块文件,这里就是我们开发的app
- build 存放的是 Gradle 在构建项目的时候生产的文件
- .gitignore 是版本控制忽略文件,和 Gradle 无关
- MyApplication.iml 生成文件,无需关心
- local.properties 存放的 SDK,NDK 在本机上的目录
- gradle.properties 存放的是整个项目 Gradle 的配置文件
- settings.gradle 存放的是这个项目包括那些模块,当前只包括一个 app 模块
项目构建脚本
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript { // 配置构建脚本
repositories { // 添加远程依赖库
jcenter() // JCenter 仓库
}
dependencies { // 配置构建依赖插件
// 声明了一个 构建 Android 的 Gradle 插件
// Gradle 本身是构建不了 Android 的
classpath 'com.android.tools.build:gradle:2.2.3'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects { // 配置整个项目
// Android 开发经常需要用一些支持库,这些支持库都有专门的网路存放地,供开发中下载
repositories { // 添加远程依赖库
jcenter() // JCenter 仓库
}
}
task clean(type: Delete) { // clean 任务清理构建生成的文件
delete rootProject.buildDir // 删除 build 文件夹
}
模块目录
- build 存放着编译生成的文件
- libs 放的是模块编译需要使用的库文件
- src 放着源码和资源文件
- .gitignore 是版本控制忽略文件,和 Gradle 无关
- app.iml 生成文件,无需关心
- build.gradle 是模块构建脚本
- proguard-rules.pro 是模块混淆规则,防止 app 被破解的
模块构建脚本
apply plugin: 'com.android.application' // 标明这个脚本是编译 android 应用程序用的
android { // 编译 apk 文件配置
compileSdkVersion 25 // SDK 版本号 API 25
buildToolsVersion "25.0.2" // 使用的编译工具的版本号
defaultConfig {
applicationId "com.io.bearzpy.myapplication" // 表明 APP 在系统中的唯一 ID
minSdkVersion 19 // 兼顾最老的系统版本
targetSdkVersion 25 // 经过充分测试的版本
versionCode 1 // 代码版本给系统实际区分不同版本
versionName "1.0" // 版本名字给人区分不同版本
// 使用单元测试框架
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes { // 构建变量
release { // 发布版本
// 这一部分是防止应用被人破解的
minifyEnabled false // 控制是否运行混淆的
// 混淆规则设置
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies { // 添加依赖
// 导入 libs 文件夹下所有的 jar 包
compile fileTree(dir: 'libs', include: ['*.jar'])
// 测试应用接口的依赖
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
// 兼容低版本系统的依赖
compile 'com.android.support:appcompat-v7:25.2.0'
// 单元测试的依赖
testCompile 'junit:junit:4.12'
}
依赖库管理
开发者经常会使用一些已有的现成的,可以直接拿来用的解决方案,这极大的提高了开发效率,也着实让他们能够偷懒了,但是这也造成了一些问题。比如当你同时使用这个两个方案解决不同的事情,这两个方案共用了同一个依赖库,但是却使用了不同的版本,这会为我们的程序带来意外的问题。Gradle 拥有解决依赖冲突的能力,它可以自动下载使用合适的版本,尽量帮开发者解决依赖库冲突问题,如果它解决不了,也会报个错给你。
编译不同的 app 版本
实际开发中,开发者往往要准备好几个版本,比如调试版本,发布版本,不同手机厂商使用的版本,都考开发者手动准备也是很费力且容易出错的。Gradle 也提供了构建多版本的功能。例如,模块构建脚本中的构建变量增加了 release 版本,我们可以在 Android Studio 的 Build Variants 里面选则 release 版本,再次编译生成的就是 release 版本了。同理,我们也可以在构建脚本中添加其他的版本,比如付费版本和免费版本等等。
Gradle 是怎么工作的
每一个 Gradle 需要完成的工作都是一个任务,这些任务之间有着先后顺序,相互依赖的关系,而 Android 应用程序的构建需要许多这样的任务。Android Studio 有 Gradle 的控制面板可以查看当前项目有哪些任务。
这是一个空的项目所拥有的任务,可以看到项目本身有相当多的任务,对应的模块还有相当多的任务。
选择一个任务双击可以运行,这里以 build 为例,Run 面板中可以看到所有被执行的任务:
小结
每当我们修改完程序之后都需要进行编译,然而编译需要这么多的步骤,如果每次都要手动去进行编译,即使能保证人工不出错,所耗费的时间也相当的大,所以有了自动化构建工具。我们在 Android Studio 中点一个 Run 就能完成的工作,实际上由自动化构建工具帮我们处理很多重复的劳动。而当旧的自动化构建工具不能满足我们的需求时,必然会有开发者去更新自动化构建工具,这也是 Android Studio 和 Gradle 成为 Android 开发使用的主流工具的原因。