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 条评论
登录 后参与评论

相关文章

来自专栏听雨堂

PowerPoint发布及链接图片的处理

        用PPT做了一个纯播放类的课件,希望发布到CD上,首先想到的是打包,找到一个PowerPoint Slide Show Converter的程序...

1718
来自专栏木头编程 - moTzxx

小程序 报错 errcode: 40029, errmsg: "invalid code, hints: [ req_id: HQd79a0747th31 ]

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

1234
来自专栏编程

在Jekyll博客添加评论系统:gitment篇

最近在Github Pages上使用Jekyll搭建了个人博客 ( jacobpan3g.github.io/cn ), 当需要添加评论系统时,找了一下国内的几...

25510
来自专栏python小白到大牛

用Python每秒钟下载一张高清大图,快不快?

如果爬虫需要展现速度,我觉得就是去下载图片吧,原本是想选择去煎蛋那里下载图片的,那里的美女图片都是高质量的,我稿子都是差不多写好了的,无奈今天重新看下,妹子图的...

991
来自专栏FreeBuf

Java代码审计丨某开源系统源码审计

java源代码审计相关资料一直比较少,今天抽空给大家写一篇简单的开源代码审计,这是个做公司网站的开源模板,由于项目比较小,本次就针对几个比较严重的漏洞讲解一下发...

1153
来自专栏木头编程 - moTzxx

微信公众平台开发[1] —— 获取用户Openid及个人信息

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

851
来自专栏一个番茄说

Cordova插件开发——滑动手势解锁(iOS篇)

第一次正儿八经的参与Cordova的项目,想写下些文字,以便日后需要的时候能够帮助自己快速回忆起来,同时也希望能够帮到需要的朋友。

651
来自专栏沈唁志

怎么防止WordPress等网站被别人使用iframe框架恶意调用?

最近发现了一个网站竟然直接使用iframe引用了全站,包括腾讯云的全站,已经通知了腾讯云的运营,运营的答复是会通过司法途径尝试去解决。个人是不可能这么干了,太麻...

783
来自专栏微信小程序开发

如何使用vue开发一个登录注册组件

本文作者:端,映客的一位前端开发。 要开发某个功能我们就要去思考这个功能怎样实现最快捷最方便,下面以项目中的登录注册组件为例说明 一个功能要尽可能的去拆分比如这...

3588
来自专栏Golang语言社区

使用Beego+Swagger构建更好的API服务

题图 By NewYorker From Twitter 一. 更好的API服务 在你已经在工作中写了很多版本,很多规范的API服务之后,你会发现,后端服务很多...

38811

扫码关注云+社区