最通俗的理解:gradle是打包用的
为什么要打包?
我们代码写完了直接run就可以了,编译通过就直接启动程序了,但是程序最终是要发布到服务器上或者是别人用的,第一你不可能让所有要运行的人都装个as,第二不可能把源代码公布给所有人。所以你需要把你的代码发布成二进制形式,让其他环境也能运行,这就是打包。
为什么用ant?
打包的时候要做很多事,比如说配置文件中的用户名和密码,你本地开发和程序实际运行时的内容肯定不一致,所以需要有两个文件,开发的时候用一个,实际运行的时候用一个。这样每次打包的时候都要重复的做这些事,ant可以让你用xml的形式把这些事情写成脚本,然后自动运行。
为什么用maven?
你的项目要用很多jar包,比如你写日志要用log4j,连数据库要用个connector。打开依赖的必要库发现里面密密麻麻好几十个jar包,不知道用哪个不用哪个,而且你一狠心把这些jar包都放进来,很大可能性还是不能运行,因为还要依赖其他的jar包。哪天想升级个库的小版本,所有jar包都要重新来一遍,你也不记得哪些库里面引进来的jar包了,
所以有了maven,你只要配置一下说我要用哪个库,左右jar包都给你下载好了,你直接运行就行了,想升级版本直接修改版本号,新的jar包也给你下载好了。
用了maven引用jar包是方便了,但我在打包的时候还是有好多事情要做啊,然后你会发现maven无法实现打包的逻辑,于是开始怀念ant。
gradle就是又能干maven的活又能干ant的活,用groove语言写脚本,表达能力还更强。
差异管理
我想设置多个不同环境下的打包渠道,有后端开发人员的本地环境、测试人员的测试环境、实际部署的生产环境等等,gradle就可以很方便的解决这个问题
productFlavors{
//开发人员1本地环境
insideNetHaoTest{
applicationId "com.example.application"
versionName "1.0.0.1.26"
versionCode 36
resValue "string","app_name","App(开发本地)"
manifestPlaceholders = [SERVICE_IP_VALUE:"xxx.168.xxx.101"
,SERVICE_PORT_VALUE:"xxxx"
,CHANNEL_VALUE:"insideNet"]
}
//测试人员测试环境
insideNetLmqTest{
applicationId "com.example.application"
versionName "1.0.0.1.31"
versionCode 36
resValue "string","app_name","App(测试环境)"
manifestPlaceholders = [SERVICE_IP_VALUE:"xxx.168.xxx.151"
,SERVICE_PORT_VALUE:"xxxx"
,CHANNEL_VALUE:"insideNetTest"]
}
//实际部署生产环境
insideNetLxdTest{
applicationId "com.example.application"
versionName "1.0.0.1.30"
versionCode 36
resValue "string","app_name","App(生产环境)"
manifestPlaceholders = [SERVICE_IP_VALUE:"xxx.168.xxx.151"
,SERVICE_PORT_VALUE:"xxxx"
,CHANNEL_VALUE:"outsideNet"]
}
...
}
依赖管理
在开发过程中肯定会依赖各种不同的库,我们可以将库的源代码下载到本地再集成到我们项目中,在gradle中有个中央仓库的概念,在这个仓库中可以找到你想要的以及你没听说的库,也就是说你可以在这个中央仓库找到所有你需要的依赖,只需要通过
implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0-alpha-14'
这样维护依赖有几点好处:
1.依赖不会进入到你的版本控制仓库中,默认会缓存到~/.gradle/下
2.方便卸载装载依赖(不需要删除再同步一下即可)
3.方便依赖的版本管理,1.1.0-alpha-14是当前依赖的版本号,若改为+就表示从中央仓库中下载最新的版本
4.不同工程的相同依赖不会存在重复副本,只在~/.gradle/下存在一份
项目部署
通过一些插件可以实现将你的输出(.jar,apk,war...)上传到指定仓库,自动部署
为什么要用Gradle?
Gradle,它是一个基于JVM的新一代构建工具,关于Gradle完全可以写一本书。Gradle目前已经应用于多个Android开发的技术体系中,比如构建系统、插件化、热修复和组件化等等,如果你不了解Gradle,那么你对于上述技术体系的了解会大打折扣。为了让大家能够更好的学习Gradle,这篇文章不会介绍Gradle具体的技术细节,而是先介绍为什么现在要用Gradle?
1.项目自动化
Gradle是一个构建工具,那么为什么要用构建工具,这就需要先从项目自动化开始讲起。 在我们开发软件时,会面临相似的情况就是,我们需要去用IDE来进行编码,当完成一些功能时会进行编译、单元测试、打包等工作,这些工作都需要开发人员手动来实现。而一般的软件都是迭代式开发的,一个版本接着一个版本,每个版本可能有很多的功能,如果开发每次实现功能时都需要手动的进行编译、单元测试和打包等工作,那显然会非常耗时而且也容易出现问题,因此项目自动化应运而生,它有以下优点: \1. 它可以尽量防止开发手动介入从而节省了开发的时间并减少错误的发生。 \2. 自动化可以自定义有序的步骤来完成代码的编译、测试和打包等工作,让重复的步骤变得简单。 \3. IDE可能受到不同操作系统的限制,而自动化构建是不会依赖于特定的操作系统和IDE的,具有平台无关性。
2.构建工具
构建工具用于实现项目自动化,是一种可编程的工具,你可以用代码来控制构建流程最终生成可交付的软件。构建工具可以帮助你创建一个重复的、可靠的、无需手动介入的、不依赖于特定操作系统和IDE的构建。这么说可能有些抽象,这里拿APK的构建过程来举例。
①通过AAPT(Android Asset Packaging Tool)打包res资源文件,比如AndroidManifest.xml、xml布局文件等,并将这些xml文件编译为二进制,其中assets和raw文件夹的文件不会被编译为二进制,最终会生成R.java和resources.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
Ant
Ant其实不是蚂蚁的意思,而是Another Neat Tool的意思,Ant的构建脚本由三个基本元素组成:一个project(工程)、多个target(目标)和可用的task(任务)。Apache Ant有以下缺点:
-
Ant无法获取运行时的信息。
-
XML作为构建脚本的语言,如果构建逻辑复杂,那么构建脚本就会又长又难以维护。
-
Ant需要配合Ivy(一种管理项目依赖工具),否则Ant很难管理依赖。
-
Ant在如何组织项目结构方面没有给出任何指导,这导致Ant虽然灵活性高,但这样的灵活导致每个构建脚本都是唯一的而且很难被理解。
Gant
Gant 是一个基于Ant 的构建工具,它在Ant的基础上用Groovy写的DSL(领域特定 语言)。如果用Ant 实现构建,但是不喜欢用XML来编写构建脚本或者现有的XML构建脚本很难维护和管理,那么Gant 是一个不错的选择。 Gant构建文件build.gant等同于此前Ant的bulid.xml。
Maven
Maven作为后来者, 继承了Ant的项目构建功能, 同样采用了XML作为构建脚本 的格式。Maven具有依赖管理和项目管理的功能,提供了中央仓库,能帮助我们自动下载库文件。
Maven相比Ant的优点:
\1. Ant是过程式的,开发者需要显示的指定每个目标,以及完成该目标锁需要执行的任务。每一个项目,开发着都需要重新编写这一过程,这样会产生大量的重复。Maven是声明式的,项目的构建过程和过程中的各个阶段都由插件实现,开发者只需要声明项目的基本元素就可以了,这很大程度消除了重复。
\2. Ant本身是没有依赖管理,需要配合Ivy来管理依赖,而Maven本身就提供了依赖管理。
\3. Maven 使用约定而不是配置,它为工程提供了合理的默认行为,项目会知道去哪个目录寻找源代码以及构建运行时有那些任务去执行,如果你的项目遵从默认值,那么只需要写几行XML配置脚本就可以了。而Ant是使用配置且没有默认行为的。
Maven的缺点:
-
Maven的提供了默认的结构和生命周期,这些可能不适合你的项目需求。
-
为Maven写定制的扩展过于累赘。
-
Maven的中央仓库比较混乱,当无法从中央仓库中得到需要的类库时,我们可以手工下载复制到本地仓库中,也可以建立组织内部的仓库服务器。
-
国内连接Maven的中央仓库比较慢,需要连接国内的Maven镜像仓库。
-
Maven缺乏文档,不便于使用和理解。
说了这么多构建工具的优缺点就是为了突出Gradle的优势,它有着约定优于配置的方法、强大的依赖管理,它的构建脚本使用Groovy或者Kotlin DSL编写,是Android的官方构建工具。下面列出Gradle优于其他构建工具的特性:
轻松的可扩展性:Gradle 有非常良好的拓展性。如果你想要在多个构建或者项目中分享可重用代码,Gradle的插件 会帮助你实现。将Gradle插件应用于你的项目中,它会在你的项目构建过程中提供很多帮助:为 你的添加项目的依赖的第三方库、为你的项目添加有用的默认设置和约定(源代码位置、单元测 试代码位置)。
采用了Groovy:Ant和Maven的构建脚本是由XML来编写的,如果XML逻辑复杂内容太多就不容易维护。Gradle可 以使用Groovy DSL来实现构建脚本,Groovy 是基于Jvm一种动态语言,它的语法和Java非常相似 并兼容Java,因此你无需担心学习Groovy的成本。Groovy在Java的基础上增加了很多动态类型和 灵活的特性,比起XML,Gradle更具有表达性和可读性。
强大的依赖管理:Gradle提供了可配置的可靠的依赖管理方案。一旦依赖的库被下载并存储到本地缓存中,我们的 项目就可以使用了。依赖管理很好的实现了在不同的平台和机器上产生相同的构建结果。
灵活的约定:Gradle可以为构建你的项目提供引导和默认值,如果你使用这种约定,你的Gradle构建脚本不会 有几行。比起Ant,Gradle不仅仅提供了约定,还可以让你轻松的打破约定。
Gradle Wrapper:Gradle Wrapper是对Gradle 的包装,它的作用是简化Gradle本身的下载、安装和构建,比如它会 在我们没有安装Gradle的情况下,去下载指定版本的Gradle并进行构建。Gradle的版本很多,所 以有可能出现版本兼容的问题,这时就需要Gradle Wrapper去统一Gradle的版本,避免开发团队 因为Gradle版本不一致而产生问题。
可以和其他构建工具集成:Gradle可以和Ant、Maven和Ivy进行集成,比如我们可以把Ant的构建脚本导入到Gradle的构建 中。
底层Api:Gradle显然无法满足所有企业级构建的所有要求,但是可以通过Hook Gradle的生命周期,来监控 和配置构建脚本。
社区的支持和推动:Gradle是一个开源的项目,它遵循了Apache License 2.0协议。Gradle的优良特性吸引了很多开发者并形成了Gradle社区,很多开源软件开发者为Gradle的核心代码做出了共享。