我们平时在 IDE 上写了很多代码,然后直接 Shift+F10 让它运行在了平台环境(Android、Windows、iOS)上。这是因为 IDE 内置了编译、打包的能力,能够将代码编译成对应平台能够直接识别和运行的二进制文件。
所以我们并不用关心 IDE 底层到底是如何编译代码的,只关心代码能不能在平台上按预期跑,有没有Bug,把注意力集中在应用层的代码逻辑实现上。
但假如你写的代码要放在用户的手机上用,你总不能让用户的手机连着你的电脑吧?亦或是你做了一个很吊的功能,别人想用这个功能,你乐意接受,但却不想将源码暴露出来,这该如何是好呢?
答案是:将代码以某种形式(二进制文件)上传到服务器上,用户下载后可以安装到手机上运行;别人也可以引用这个代码能力,同时查看不到所有的源码。
比如我们所熟知的 .dex
(Andorid)、.class
(Java)、.pyc
(python)都是经转化后能够被特定平台所识别的二进制文件。
我们一般把:
虽然用了短短几个词进行概括,但在底层则是做了一系列的事情,例如 代码编译
、依赖管理
、签名
、资源编译
、混淆
、对齐
等等操作。每些操作都需要依赖独特的工具,很明显,我们这些上层开发肯定是不会参与到这一流程中的,而是交给一套脚本工具,让脚本工具去集成 / 组合这些操作,然后按照顺序执行命令,实现自动化一条龙服务。我们平时写完代码后,点击“运行”其实就是让这套脚本工具开始运作。
如下图所示,从应用代码到生成 Apk 需要经历多个步骤,为了减少人工成本,需要自动化地去顺序执行这些操作,这就是构建脚本存在的意义。
在我们的 Java 领域上,有这些脚本工具和配套工具:
Ant
Maven
Gant
Gradle
下面一一来介绍它们。
Ant
是由 Apache 公司开发的用于 Java 编译、测试、部署的自动化工具。 其脚本语言是 XML
。
它内置了 javac
、 java
、创建 / 复制目录等功能,所以可以直接编译我们的 Java 代码生成实际项目。
每个脚本工具都会有一个默认的构建代码的文件,对于 Ant
来说,叫做:build.xml
,它长这个样子:
它有几个标签,介绍其中几个重要的标签:
:生成文件的根元素,表示一个工程
: project的子元素,表示一个任务; 一个project中可以定义多个target元素,表示多个任务
:打包成 jar 包, destifile
为打包之后的名称, basedir
则为需要打包的 java 文件目录
:运行 java 类, classname
指定运行类的名称, classpath
指定运行类所在的目录Ant
是十分著名的 Java 自动化脚本工具,它的出现是为了解决早期的 Linux
的脚本工具 Make
的痛点,自发布以来,深受广大 Java 开发的青睐。但是 Ant 也有一些局限性和缺点,比如:
Ant
很难管理依赖,一般都要配合 Ivy
(一种管理项目依赖的工具) 使用;Ant
无法获取运行时的信息;XML
作为脚本语言有一定的局限性,例如构建逻辑复杂时, XML
的代码将会很长,维护成本较大;Ant
并没有为 Java 的自动化构建提供一个标准流程,其默认脚本文件一无所有,非常的灵活,需要开发者手动定制每个阶段的构建,这会导致大伙不清楚怎么样写脚本才是标准的,为此而苦恼。Maven
继承了 Ant
的项目构建功能,同样使用 XML
作为脚本语言,但它解决了很多 Ant
的痛点,例如:
Ant
过于灵活(开发需要从头到尾编写一份) 的问题,提供的默认脚本文件 pom.xml
里面帮我们定好了一套构建流程,我们在其给定好的标签里发挥就行。使得开发者不必在为“什么才是标准的构建流程代码”而苦恼了。4.0.0 com.mycompany.app my-app 1.0 junit junit 3.8.1 test
Ant
需要依赖 Ivy
工具的问题。 Maven
提供公共的中央仓库,即脚本工具自身提供依赖管理能力。Central Repository
)动态地下载 Java 库与 Maven 插件,并将其存储在本地缓存区中Gant
也是一个基于 Ant
的构建工具,但这一次它不再使用 XML
做为脚本语言,而是使用 Groovy
语言做为脚本语言。
IDEA 默认支持 Gant
,它能识别 .gant
结尾的文件, build.gant
就是其默认构建脚本文件,等同于 build.xml
。可以看下这个文件:
Ant.echo(message : 'running build.gant')
Ant.property(file : 'build.properties')
def antProperty = Ant.project.propertiestarget(hello : 'say hello target') {depends(init)echo(message : antProperty.'echo.msg')
}setDefaultTarget(hello)
Gant 和 Ant 的关系,就像是 Retrofit 和 OkHttp 的关系那样,通过使用 Groovy 语言来调用 Ant 的能力。不过 Groovy
语言相较于 XML
能够在写出复杂逻辑的构建代码时,提供不错的可读性,很多场景完全可以使用 Gant 来替代 Ant。
终于来到我们的主角:Gradle
,它拥有上述几个脚本工具所具有的优点:
Groovy
作为脚本语言,在编写复杂构建逻辑时,能保持优良的可读性和重用性,并且很灵活,不像 XML
那样受限于只能描述数据而非流程的特性;Kotlin
来编写,对 Android 开发者来说非常之友好;Gradle Wrapper
可以帮我们下载和管理 Gradle 版本,因为 Gradle 有多个版本,不同项目可能使用的是不同版本的Gradle,这个时候为了能够运行别人的项目,可以通过 Gradle Wrapper
来了解别人的构建版本,然后通过下载或修改使之能够运行在我们的电脑上;它的默认脚本工具是 build.gradle
,长这样:
plugins {id 'com.android.application'
}
android {defaultConfig {applicationId "com.example.gradle_demo"minSdk 21}buildTypes {release {minifyEnabled falseproguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'}}compileOptions {sourceCompatibility JavaVersion.VERSION_1_8targetCompatibility JavaVersion.VERSION_1_8}kotlinOptions {jvmTarget = '1.8'}
}dependencies {implementation 'androidx.core:core-ktx:1.7.0'implementation 'androidx.appcompat:appcompat:1.5.1'
}
总之,Gradle 已经成为 JVM 上首选构建工具,作为一名 Android 程序员,我们甚至不用学习 Groovy
,而是直接使用 Kotlin
来学习就好了。
若要成为一名优秀的 Android 开发者,不仅要对应用层、Framework层有深刻的理解,还需掌握 Gradle
,深入打包、发布流程。
Gradle
是 Android 开发息息相关的一门技术,由于 IDE 高度集成了 Gradle,大部分人平时基本和 Gradle 打不上交道,很多应用层开发者对这方面的认知较为浅薄,知识点零散。
通过学习 Gradle,除了了解编译、打包的知识,我们还能够进阶:因为很多 Android 技术都会涉及到 Gradle, 例如 自动化、热修复、组件化、系统构建等,如果不会 Gradle,那势必也学不好这些技术。
这里我根据整理来的知识,罗列一下学习清单:
主要不求过于深入,但求覆盖所有基础知识点。
Gradle - Wiki
如何通俗理解 Gradle? - 知乎
Gradle核心思想(一)为什么现在要用Gradle?