Gradle for Android 系列:为什么 Gradle 这么火

Android 应用的构建过程

Android 应用程序的构建过程非常复杂,如图所示:

主要有以下几步:

  1. 主要的资源文件(layout, values 等)都被 aapt 编译,并且在一个 R 文件中引用
  2. Java 代码被 Java 编译器编译成 JVM 字节码(.class 文件)
  3. JVM 字节码再被 dex 工具转换成 dalvik 字节码(.dex 文件)
  4. 然后这些 .dex 文件、编译过的资源文件和其他资源文件(比如图片)会被打包成一个 apk
  5. apk 文件在安装前会被 debug/release 的 key 文件签名
  6. 安装到设备

几个注意点

  1. 上面的步骤中第一步注意是主要的资源文件,有些特别的资源文件就不会被编译,比如 assets 目录下的文件,raw 目录下的文件还有图片,都不会被编译。只不过 raw 下的文件会在 R 文件里生成 id
  2. 如果对 apk 正式签名,还需要使用 zipalign 工具对 apk 进行对齐操作,这样做的好处是当应用运行时会减少内存的开销

通过上面的介绍可以看到,这么复杂的构建过程如果需要人手动去完成未免太过残忍,于是有了各种的构建工具。

Android 构建的旧爱:Ant, Maven

在 Gradle 之前被广泛使用的是 Apache Ant 和 Maven。

Ant

Ant 2000 年发布,很快成为 Java 项目最流行的构建工具。

Ant 的优点就是: - 简单、易学,不需要什么特殊准备就能上手 - 基于过程式编程思想使得构建非常灵活 - 后来还能支持插件。

不足之处就是使用 XML 作为脚本配置格式,除非是很小的项目,否则它的 XML 文件很快就大得无法管理。

Maven

Maven 发布于 2004 年。目的是解决使用 Ant 所带来的一些问题。

Maven 也是使用 XML 作为构建配置的文件格式,不过文件结构却有了巨大的变化:

  • Ant 需要开发者将执行 task 所需的全部命令都列出来
  • 而 Maven 依靠约定并提供现成的可调用的目标

不仅如此,Maven 更重要的一个进步是具备从网络上自动下载依赖的能力(当然 Ant 后来通过 Ivy 也具备了这个功能),这革命性地改变了我们开发软件的方式。

Maven 的缺点是:

  • 依赖管理不能很好地处理相同库文件不同版本之间的冲突(Ivy在这方面更好一些)
  • XML 作为配置文件的格式有严格的结构层次和标准,定制化目标很困难

Maven 主要解决了依赖管理的问题,然而使用 XML 的错误使它重蹈覆辙,实际上用 Maven 很难写出复杂、定制化的构建脚本,在大型项目中,它经常什么“特别的”事还没干就有几百行代码,甚至不如 Ant。

前辈们在反省前两种构建工具的错误之后,提出了 DSL (Domain Special Language, 领域专用语言)的概念,目标是设计一套能够解决特定领域问题的语言。在构建这方面,DSL 的一个成功案例就是 Gradle。

Android 构建的新欢:Gradle

2012 年发布的 Gradle 深刻吸取前面几位前辈的经验和教训,集大家之所成,做了很多改进。

Gradle 有约定优于配置的原则,即为设置和属性提供默认值,这使得它比 Ant 或者 Maven 更容易上手。

Gradle 构建脚本不再使用 xml ,而是使用基于 Groovy 的 DSL 进行书写(Groovy 是一种基于 Java 虚拟机的动态语言,因此 Android 开发者看着会很熟悉),从而使得构建脚本比用 Ant 和 Maven 写的更清晰、简洁,下面是实现同样目标的 Maven 代码和 Gradle 代码对比:

Gradle 既有 Ant 的强大和灵活,又有 Maven 的依赖管理,支持插件且易于使用。因此一推出就获得广泛关注,2013 年被 Google 选为 Android Studio 的默认构建工具。

Gradle 设计的方式使得它可以很容易地扩展构建和插入到现有的构建过程中,Google 推广 Gradle 和 Android Studio 时,目标是让代码复用、构建 variant、配置和定制构建过程变得更加简单。

有人可能担心是否需要专门去学习新语言 Groovy,《Gradle for Android》书中专门提到:

Groovy 代码非常易读,如果你学习过 Java,那么学习 Groovy 的曲线不会陡峭。 如果你想构建自己的任务和插件,那么对 Groovy 有更深层次的理解尤为重要。 不过因为 Groovy 是基于 Java 虚拟机的,所以你完全可以用 Java 或者其他基于 Java 虚拟机的语言来编写你的自定义插件。

Gradle 的关键概念及构建生命周期

Gradle 中两个关键的概念:项目和任务。

每个 build.gradle 构建脚本文件代表一个项目 project:

任务 task 定义在构建脚本里:

每次构建至少包括一个项目,每个项目里又至少包括一个任务。

构建生命周期

一个 Gradle 构建通常包括下面三个阶段:

  1. 初始化
    • 项目实例会在这时被创建,如果这个项目里有多个 module,或者依赖多个 library,并且它们都有对应的 build.gradle 文件,就会创建多个项目实例
  2. 配置
    • 在这个阶段构建脚本被执行,并且为每个项目实例创建和配置任务
  3. 执行
    • 在这个阶段 Gradle 将根据构建脚本的配置决定哪些任务会被执行

不同任务之间可能有 相互依赖,因此在配置阶段 Gradle 会生产依赖关系图,没有依赖的任务通常会被优先执行,然后一个接一个执行其他任务。一旦一个任务被执行过,就不会被再次执行。

Gradle Wrapper

Gradle 在不断的发展,有可能存在新版本不兼容旧版本的情况,于是官方为我们提供了 Gradle Wrapper,就是为了兼容和适配不同版本,确保构建是可重复的。

普通的 Gradle 脚本命令是:

gradle ...

而 Gradle Wrapper 命令只是在 gradle 后加了个 w:

gradlew ...

在 Mac 下略微有些不同:

./gradlew ...

开发者或者自动构建系统可以通过使用 wrapper 来运行 gradle 命令,由它来搞定兼容等问题。因此我们甚至都不需要安装 gradle,直接使用 gradle wrapper 即可,就像 Android Studio 里推荐的一样:

上图我并没有使用 wrapper,是因为当你运行 gradlew 命令时,gradle wrapper 会自动下载需要但是你没有的 gradle 版本并使用。 这在多人协作时,很可能因为别人修改了 gradle 版本、上传到 git,然后导致你运行命令时需要下载半天。

不过官方还是推荐使用 wrapper,毕竟这样更稳定。

使用 gradle wrapper 以后,gradle wrapper 会为每个项目下载一个 gradle 压缩包,路径在 \Users\yourname.gradle\wrapper\dists 里:

总结

Android Studio 占领市场后,构建工具 Gradle 的地位无人能比,我们有必要学习、使用它来为我们创造价值。

这篇文章对比 Ant 和 Maven 泛泛而谈了 Gradle 的一些优点,在理解 Gradle 为什么会被使用、它有什么优点之后,有助于我们后续深入学习 Gradle 的使用。

Thanks

《Gradle for Android》 https://technologyconversations.com/2014/06/18/build-tools/ https://www.kancloud.cn/digest/androidframeworks/127789 http://www.drdobbs.com/jvm/why-build-your-java-projects-with-gradle/240168608

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏吴伟祥

Spring Boot 之 spring-boot-devtools 实现热部署

选择“Registry”,回车,找到“complier.automake.allow.when.app.running” 

693
来自专栏每日一篇技术文章

weex-24-modal模块

如果你觉得这些界面颜色风格和你的应用配色格格不入,你可以自定义自己想要的类似的组件!

481
来自专栏阿杜的世界

Spring Boot应用的打包和部署

现在的IT开发,DevOps渐渐获得技术管理人员支持、云计算从ECS转向Docker容器技术、微服务的概念和讨论也越来越热,以上这些研究方面,最终都聚焦于软件的...

893
来自专栏极客慕白的成长之路

DNS预解析详解

DNS解析时间可能导致大量用户感知延迟,DNS解析所需的时间差异非常大,延迟范围可以从1ms(本地缓存结果)到普遍的几秒钟时间。所以利用DNS预解析是有意义的。

1374
来自专栏轻量级微服务

微服务下使用网关 Spring Cloud Gateway

客户端向 Spring Cloud Gateway 发出请求,如果请求与网关程序定义的路由匹配,则将其发送到网关 Web 处理程序,此处理程序运行特定的请求过滤...

530
来自专栏Danny的专栏

探秘Oracle表空间、用户、表之间的关系

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/huyuyang6688/article/...

692
来自专栏Kubernetes

原 荐 基于Kubernetes的ESaaS

概述 ESaaS(ElasticSearch as a Service)是ElasticSearch on Kubernetes的产品实现,是利用Docker和...

2968
来自专栏程序猿DD

Swagger Starter 1.4.0发布:新增swagger功能开源与全局参数的配置。

该项目主要利用Spring Boot的自动化配置特性来实现快速的将swagger2引入spring boot应用来生成API文档,简化原生使用swagger2的...

3526
来自专栏YouMeek

使用 Github 空间搭建 Hexo 博客 2–增强篇

主题优化 主题配置介绍 我这里只讲自己在使用的 yelle 主题,你可以参考下,可能还有一些改动我后续会自己在慢慢改,但是大体基本也就这样了。 从中我们也可以看...

3347
来自专栏后端之路

动静分离之上传CDN

动静分离的好处就不用多说了,使用cdn也是常见的前端优化手段之一,针对全国范围内不同地区不同网络环境的用户可以获得较好的体验。 在jsp或者其他模板引擎定义对...

2288

扫码关注云+社区