笔记来源于以下文章
1. http://liuwangshu.cn/application/gradle/1-study-gradle.html
2. https://blog.csdn.net/singwhatiwanna/article/details/76084580
1. 为什么是Gradle
Gradle是目前Android主流的构建工具,不管你是通过命令行还是通过AndroidStudio来build,最终都是通过Gradle来实现的,所以学习Gradle非常重要。
目前国内对Android领域的探索已经越来越深,不少技术领域如插件化、热修复、组件化、构建系统等都对Gradle有迫切的需求,不懂Gradle将无法完成上述事情,所以Gradle必须要学习。
2. 项目自动化
Gradle是一个构建工具,为什么要用构建工具,这里就需要先从项目自动化开始讲起。
在我们开发软件时,会面临相似的情况就是,我们需要去用IDE来进行编码,当完成一些功能时会进行编译、单元测试、打包等工作,这些工作都需要开发人员手动来实现。而一般的软件都是迭代式开发的,一个版本接着一本版本,每个版本又可能有很多的功能,如果开发每次实现功能时都需要手动的进行编译、单元测试和打包等工作,那显然会非常耗时而且也容易出现问题,因此项目自动化应运而生,它有以下优点:
- 它可以尽量防止开发手动介入从而节省了开发的时间并减少错误的发生。
- 自动化可以自定义有序的步骤来完成代码的编译、测试和打包等工作。
- IDE可能受到不同操作系统的限制,而自动化构建是不会依赖于特定的操作系统和IDE的,具有平台无关性。
3. 构建工具
构建工具用于实现项目自动化,是一种可编程的工具,你可以用代码来控制流程,最终生成可交付的软件。构建工具可以帮助你创建一个重复的、可靠地、无需手动介入的、不依赖于特定操作系统和IDE的构建。下面拿APK的构建过程来举例。
3.1 APK的构建过程
APK的构建过程可根据官方提供的流程图如下图所示
APK的构建过程主要分为以下几步:
- 通过AAPT(Android Asset Packaging Tool)打包res资源文件,比如AndroidManifest.xml、xml布局文件,并将这些xml文件编译为二进制,其中assets和raw文件夹的文件不会被编译为二进制,最终会生成R.java和resource.arsc文件。
- AIDL工具会将所有的aidl接口转化为对应的Java接口。
- 所有的Java代码,包括R.java和Java接口都会被Java编译器编译成.class文件。
- Dex工具会将上一步生成的.class文件、第三方库和其他.class文件编译成.dex文件。
- 上一步编译生成的.dex文件、编译过的资源、无需编译的资源(如图片等)会被ApkBuilder工具打包成APK文件。
- 使用Debug Keystore或者Release Keystore对上一步生成的APK文件进行签名。
- 如果是对APK正式签名,还需要使用zipalign工具对APK进行对齐操作,这样应用运行时减少内存的开销。
以上步骤可以看出,APK的构架过程是比较繁琐的,而且这个构建过程又是时常重复的,如果没有构建工具,手动去完成构建工作,无疑对于开发人员是个折磨。也会可能在过程中产生很多问题,导致项目开发周期变长。
在Gradle出现之前,有三个基于Java的构建工具:Ant、Gant和Maven,他们被应用于Java或者Android开发中,下面简单介绍一下:
2.2 Apache Ant
imageAnt在这里不是蚂蚁的意思(虽然它的图标是蚂蚁),而是Another Neat Tool的意思。
它是由 James Duncan Davidson 开发的(Tomcat 最初的开发者),最初是用来构建 Tomcat。在2000年,Ant成为一个独立的项目并被发布出来。Ant 是由 Java 编写的构建工具,它的核心代码是由Java编写的,因此具有平台无关性,构建脚本是XML格式的(默认为bulid.xml),如果你熟悉XML,那么Ant 就比较容易上手。
Ant构建脚本的样式如下所示。
build.xml
<?xml version="1.0" encoding="UTF-8"?>
<project name="test" default="hello">
<echo message="running build.xml which is equivalent to build.gant"/>
<property file="build.properties"/>
<target name="init" description="init target" >
<echo message="Executing init target"/>
</target>
<target name="hello" depends="init" description="say hello target">
<echo message="${echo.msg}"/>
</target>
</project>
Ant的构建脚本由三个基本元素组成:一个project(工程)、多个target(目标)和可用的task(任务)。
Apache Ant有以下缺点:
- Ant无法获取运行时的信息。
- XML作为构建脚本的语言,如果构建逻辑复杂,那么构建脚本就会又长又难以维护。
- Ant需要配合lvy(一种管理项目的依赖工具),否则Ant很难管理依赖。
- Ant在如何组织项目结构方面没有给出任何知道,这导致Ant虽然灵活性高,但这样的灵活导致每个构建脚本都是唯一的而且很难被破解。
3.3 Gant
[图片上传失败...(image-fa2b53-1551348478092)]
Gant 是一个基于Ant 的构建工具,它在Ant的基础上用Groovy写的DSL(领域特定语言)。如果用Ant 实现构建,但是不喜欢用XML来编写构建脚本或者现有的XML构建脚本很难维护和管理,那么Gant 是一个不错的选择。
Gant构建文件的样式如下所示。
build.gant
Ant.echo(message : 'running build.gant')
Ant.property(file : 'build.properties')
def antProperty = Ant.project.properties
target(init : 'init target') {
echo(message : 'Executing init target')
}
target(hello : 'say hello target') {
depends(init)
echo(message : antProperty.'echo.msg')
}
setDefaultTarget(hello)
这个build.gant等同于此前Ant的bulid.xml
3.4 Apache Maven
imageMaven于2004年发布,它的目标是改进开发人员在使用Ant时面临的一些问题。Maven最初是为了简化Jakarta Turbine项目的构建,它经历了Maven到Maven3的发展,Maven作为后来者, 继承了Ant的项目构建功能, 同样采用了XML作为构建脚本的格式。Maven具有依赖管理和项目管理的功能,提供了中央仓库,能帮助我们自动下载库文件。
Maven的构建脚本样式如下
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.mycompany.app</groupId>
<artifactId>my-app</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>Maven Quick Start Archetype</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
Maven相比Ant的优点:
- Ant是过程式的,开发者需要显示的指定每个目标,以及完成该目标锁需要执行的任务。每一个项目,开发着都需要重新编写这一过程,这样会产生大量的重复。Maven是声明式的,项目的构建过程和过程中的各个阶段都由插件实现,开发者只需要声明项目的基本元素就可以了,这很大程度消除了重复。
- Ant本身是没有依赖管理,需要配合Ivy来管理依赖,而Maven本身就提供了依赖管理。
- Maven 使用约定而不是配置,它为工程提供了合理的默认行为,项目会知道去哪个目录寻找源代码以及构建运行时有那些任务去执行,如果你的项目遵从默认值,那么只需要写几行XML配置脚本就可以了。而Ant是使用配置且没有默认行为的。
Maven的缺点:
- Maven提供了默认的结构和生命周期,这些可能不适合你的项目。
- 为Maven写定制的扩展过于累赘。
- Maven的中央仓库比较混乱,当无法从中央仓库中的带需要的类库时,我们可以手工下载复制到本地仓库中,也是建立组织内部的仓库服务器。
- 国内连接Maven的中央仓库比较慢,需要连接国内的Maven镜像仓库。
- Maven缺乏文档,不便于使用和理解。
4. Gradle的特性
Gradle是一款基于JVM的专注于灵活性和性能的开源构建工具。
build.gradle
apply plugin:'java'
group='com.mycompany.app'
archivesBaseName='my-app'
version='1.0-SNAPSHOT'
repositories{
mavenCentral()
}
dependencies{
testCompile 'junit:4.11'
}
这个build.gradlet等同于此前Maven的pom.xml。可以看出Groovy编写构建脚本代码量更少,可读性更强。
下面列出Gradle与竞争对手不同的特性。
4.1 轻松地可扩展性
Gradle有非常良好的拓展性。如果想要在多个构建或者项目中分享可重用代码,Gradle的插件会帮助你实现。将Gradle插件应用于你的项目中,它会在你的项目构建过程中提供很多帮助:为你的添加项目的依赖的第三方库、为你的项目添加有用的默认设置和约定(源代码位置、单元测试代码位置)。其中Android Gradle插件继承Java Gradle插件,在本系列后续的文章会介绍插件的内容。
4.2 采用了Groovy
Ant和Maven的构建脚本是由XML来编写的,如果XML逻辑复杂内容太多就不容易维护。Gradle可以使用Groovy来实现构建脚本,Groovy是基于Jvm一种动态语言,它的语法和Java非常相似并兼容Java,因此你无需担心学习Groovy的成本。Groovy在Java的基础上增加了很多动态类型和灵活的特性,比起XML,Gradle更具有表达性和可读性。
4.3 强大的依赖管理
Gradle提供了可配置的可依靠的依赖管理方案。一旦依赖的库被下载并存储到本地缓存中,我们的项目就可以使用了。依赖管理很好的实现了在不同的平台和机器上产生相同的构建结果。
4.4 灵活的约定
Gradle可以为构建你的项目提供引导和默认值,如果你使用这种约定,你的Gradle构建脚本不会有几行。比起Ant,Gradle不仅仅提供了约定,还可以让你轻松的打破约定。
4.5 Gradle Wrapper
Gradle Wrapper是对Gradle的包装,它的作用是简化Gradle本身的下载、安装和构建,比如它会在我们没有安装Gradle的情况下,去下载指定版本的Gradle并进行构建。Gradle的版本很多,所以有可能出现版本兼容的问题,这时就需要Gradle Wrapper去统一Gradle的版本,避免开发团队因为Gradle版本不一致而产生问题。
4.6 可以和其他构建工具继承
Gradle可以和Ant、Maven和lvy进行继承,比如我们可以把Ant的构建脚本导入到Gradle的构建中。
4.7 底层API
Gradle显然无法满足所有企业级构建的所有要求,但是可以通过Hook Gradle的生命周期,来监控和配置构建脚本。
4.8 社区的支持和推动
Gradle是一个开源的项目,它遵循了Apache License2.0协议。Gradle的优良特性吸引了很多开发者并形成了Gradle社区,很多开源软件开发者为Gradle的核心代码做出了分享。
5. 如何学习Gradle
大部分人对Gradle表示一脸懵逼,每当遇到一个问题的时候都需要从网上去查,这是一个误区。
Gradle不单单是一个配置脚本,它的背后是几门语言,如果硬让我说,我认为是三门语言。
Groovy Language
Gradle DSL
Android DSL
DSL的全称是Domain Specific Language,即领域特定语言,或者直接翻译成“特定领域的语言”,算了,再直接点,其实就是这个语言不通用,只能用于特定的某个领域,俗称“小语言”。因此DSL也是语言。
在你不懂这三门语言的情况下,你很难达到精通Gradle的程度。这个时候从网上搜索,或者自己记忆的一些配置,其实对你来说是很大的负担。但是把它们当做语言来学习,则不需要记忆这些配置,因为语言都是有文档的,我们只需要学语法然后查文档即可,没错,这就是学习方法,这就是正道。
6. 总结
本篇文章从项目自动化开始讲起,介绍了常用的构建工具:Ant、Gant和Maven,最后介绍了Gradle的特性,这些特性和其他竞争的构建工具相比有着很大的优势和吸引力,这也是为什么我们现在要用Gradle的原因。
网友评论