在写这篇博客时,搜索参考了很多资料,网上对于 Groovy 介绍的博客已经特别多了,所以也就没准备再详细的去介绍 Groovy,本来也就计划写一些自己认为较重要的点。后来发现了 Groovy 的官方文档后,发现其实官方的介绍特别的全面,详细。但可惜的是我的英语不好,看英文文档有些费时间,但还是推荐有能力的人去参照官方文档来学习,后期如果有时间的话,我也计划试着翻译一些官方的文档来学习,记录一下。

所以,这篇的侧重点不是在介绍 groovy 的基本语法,而是介绍跟 build.gradle 比较相关的一些知识点吧,另外在末尾会附上一些 groovy 学习链接,有兴趣的可以继续去学习。


系列索引

build.gradle系列一:看不懂的build.gradle代码

build.gradle系列二:学点Groovy来理解build.gradle代码

build.gradle系列三:如何用Adnroid Studio查看build.gradle源码

...


开始学习 Groovy 前,引用徐宜生的《Android群英传:神兵利器》书中的一句话来介绍 Groovy:

Groovy 对于 Gradle,就好比 Java 对于 Android。了解一些基本的 Groovy 知识,对于掌握 Gradle 是非常有必要的。

Groovy 是什么

Groovy 是一种脚本语言,既然是脚本语言,那么它也就有脚本语言的那些特点:使用动态类型、末尾不用分号等等。另外,它又是基于 Java 上设计的语言,也就是 Groovy 兼容 Java,可以使用 JDK 里的各种方法,你可以在 Groovy 文件里写 Java 代码里,照样可以正常编译运行。

Groovy 语法

关于语法的详细的介绍在末尾有链接,这里就只是挑出我认为比较重要的,而且跟 java 有区别的,在阅读代码时可能会看不懂的一些语法进行记录。

1.注释、标识符方面跟 Java 基本一样。

2.基本数据类型,运算方面

这方面在 build.gradle 文件里也不怎么常见到使用,因为 groovy 是动态类型,定义任何类型都可以只使用 def 来定义,所以如果使用具体的比如 char, int 等类型时需要强制转换吧。有需要的可以自己查阅末尾的参考链接。

3.字符串方面

java 只支持用 "..." 双引号来表示字符串

groovy 支持使用 '...', "...", '''...''', """...""", /.../, $/.../$ 即单引号,双引号等6种方法来表示字符串

至于各种表示方法有什么区别,具体可以参考末尾的链接,这里简单提提,'...', "..." 只支持单行字符串,不支持多行,剩下的四种都支持多行字符串,如下图



斜杠我也很少见,常见的是带有 ${} 的字符串,比如: println "blog's url: ${blogUrl}" 这是 groovy 的 GString 特性,支持字符串插值,有点了类似于变量引用的概念,但注意,在 '...', '''...''' 单引号表示的字符串里不支持 ${}。当然,如果你要使用 java 的方式,用 + 来拼接也可以。

4.集合方面(List、Map)

定义和初始化

定义很简单,List 的话使用 [] 定义,各项用 , 隔开即可。Map 的话使用 [:],各项也是用 , 隔开,如:

def numList = [1, 2, 3]  //List
def map [1:"dasu", dasu:24] //Map, : 前是key,如1, : 后是value, 如dasu

有一点跟 java 不同的是, groovy 集合里不要求每一项都是同类型,比如可以这样定义 def list = [1, 'dasu', true],集合里包含数字,字符串,布尔值三种类型。

使用

通过下标操作符 [] 读写元素值,并使用正索引值访问列表元素或负索引值从列表尾部访问元素,也可以使用范围,或使用左移 << 追加列表元素,如

//========= List 使用 ================
println numList[1] //输出 1
println numList[-1] //输出 3 numList[2] = 4 // println numList[2]将输出 4
numList[3] = 5
numList << "dasu" //现在numList = [1, 2, 4, 5, "dasu"] //========== Map 使用 ================
println map[1] //输出 dasu
println map.dasu //输出 24, key是字符串的话可以这样访问
map[3] = "I am dasu" // 在map里加入一个[3:"I am dasu"]项

跟 java 不同的是, groovy 并不存在下标访问越界,当下标为负数时则从右开始算起,当指定的下标没有存放值时返回 null。

5.数组方面

groovy 其实没有严格区分数组和集合,数组的定义和使用方法跟集合一样,只是你需要强制声明为数组,否则默认为集合,如

String[] arrStr = ['Ananas', 'Banana', 'Kiwi']
def numArr = [1, 2, 3] as int[] //as 是 groovy 关键字

上面的初始化方式是不是跟 java 不一样,这一点需要注意下,java 是用 {} 来初始化,但在 groovy 里面, {} 表示的是闭包,所以这点需要注意一下。


上面的是 groovy 与 java 不同的一些基本语法,下面介绍一些我自己认为是 groovy 比较重要的特性,如果要看懂 build.gradle 里的代码,明白下面介绍的会比较有帮助。

6.方法的简化使用

方法的括号可以省略

groovy 定义方法时可以不声明返回类型和参数类型,也可以不需要 return 语句,最后一行代码默认就是返回值。

而在调用方法时可以将括号省略,不省略的时候如下

def add(a, b) {
a + b
}
println add(1,2) //输出 3

上面的方式不陌生吧,再来看看下面的代码

println add 1, 2 //输出 3, add方法同上

上面就是调用方法时省略掉圆括号的写法,再来看一种情况

def getValue(Map map) {
map.each {
println it.key + ":" + it.value
}
}
def map = [author:"dasu"]
getValue(map) //输出 author:dasu

这次定义一个参数为 map 类型的方法,如果我们在调用方法的时候才对参数进行定义和初始化会是什么样的呢?如下

getValue(author: "dasu") //输出 author:dasu

之前说过了,groovy 调用方法时可以将括号省略掉,这样一来再看下

getValue author: "dasu" //输出 author:dasu

这样子的格式是不是看着觉得很眼熟,没错,就是 build.gradle 里的第一行代码。



如果有看过我的上一篇 build.gradle 博客的话,现在对疑问1是不是就有些理解了呢。

上图那代码如果把省略的括号补上的话,大家应该就会熟悉点了

// apply plugin: 'com.android.application'  等效于
def map = [plugin: 'com.android.application']
apply(map)

调用了 apply() 方法,该方法传入一个 map 参数,我们来看看是不是这样,用as查看下源码,如下



没错吧,apply() 其实是个方法,参数为 map 类型,而且 key 的取值也给你规定了 from, plugin, to 三种,是不是确实在别人的 build.gradle 代码里也有看见过类似 apply from ***,这样一来就明白多了吧。

好了,然后你再重新去看一下 build.gradle 里的代码,是不是对每一行的代码都有了新的看法了。

其实 build.gradle 里的每一行代码都是在调用一个方法,比如下面这些我们常见的:



每一行都是在调用一个方法,前面是方法名,后面是方法的参数,只是把括号省略掉了而已,感兴趣的你可以再自己用as点进去看看源码是不是这样。

方法最后一个参数是闭包可以提取出来接到后面

闭包是 groovy 的一大特性,我理解也不深,也讲不大清楚,感兴趣的可自行网上查阅学习,简单的说就是一个用 {..} 包起来的代码块,比如 build.gradle 里的 defaultConfig{...}, buildTypes{...}, dependencies{...} 等等这些大括号包起来的代码块就是闭包,闭包代码块最后一句代码作为闭包的返回值。

当闭包作为方法的最后一个参数,可以将闭包从参数圆括号中提取出来接在最后,如果闭包是唯一的一个参数,则方法参数所在的圆括号也可以省略。对于有多个闭包参数的,只要是在参数声明最后的,均可以按上述方式省略,举个例子。

//定义 add 方法
def add(a, Closure c) {
println a + c.call()
}
//调用方法
add(1, {1+1}) //输出 3

上面定义一个 add 方法,最后一个参数为闭包,调用的时候传入一个闭包,闭包的最后一行代码 1+1 作为闭包返回值返回,闭包返回值作为方法的第二个参数传入方法中计算加法,所以最终输出3。上面的调用也可以写成下面的方式:

add(1){
1+2
} //输出 4

注意,这是调用 add() 方法,而不是在定义,1 是第一个参数,括号后的闭包 { 1+2 } 是方法的第二个参数,这就是 groovy 的特性,闭包可以提取出来。那么再想想,如果方法只有一个闭包参数,再结合 groovy 可以省略掉括号的特性,这样子调用一个方法将会是什么样子呢?

//定义 method 方法
def method(Closure c) {
println c.call()
}
//调用方法
method {
I'm dasu
} //输出 I'm dasu

是不是又感觉很熟悉,对吧,就是 build.gradle 里的 defaultConfig{...}, buildTypes{...}, dependencies{...} 等等这些。

所以,结合上面讲的两点:可以省略方法括号和闭包可以提取接到括号后面,这样一来, build.gradle 里的代码其实就是在调用各种方法,defaultConfig 是一个方法,compileSdkVersion 也是一个方法。 build.gradle 里的每一行代码前面是方法名,后面则是方法需要的参数,参数有的是基本类型,有的则是闭包类型。

集合遍历 each/all

就先把上一篇博客里的在一段在 build.gradle 里很常见的代码贴出来

这段代码作用就是对打包生成的 apk 按照规定的格式进行重命名,在很多大神的 build.gradle 里都会遇见过,其实这一段代码就是 groovy 代码,alleach 是集合的一种操作,all 后面跟着的是一个参数为 variant 的闭包,表示对 applicationVariants 集合里所有的对象都运行后面的闭包,同理 each 后面也是跟着一个参数为 output 的闭包,类似于 java 里的 for 循环操作。所以这里要理解的应该是 applicationVariants 代表的是什么,这点我也还不是很懂,后面如果搞懂了的话会在之后的博客里介绍出来。

另外,我还有个疑问来着, all 操作和 each 操作有什么区别么,感觉都是对集合里所有的元素进行操作,如果有懂的能够告知就太感谢了,查了挺多资料貌似还不是很明白。

参考资料

官方文档

Groovy语言规范-语法(官方文档翻译)

Groovy操纵集合秘籍




最近刚开通了公众号,想激励自己坚持写作下去,初期主要分享原创的Android或Android-Tv方面的小知识,感兴趣的可以点一波关注,谢谢支持~~

学点Groovy来理解build.gradle代码的更多相关文章

  1. build.gradle代码

    Android Studio 这么强大的工具,就算我们不懂 gradle, groovy, 也照样能借助AS对 Android 项目进行编译.调试.运行.打包等操作.build.gradle 这个文件 ...

  2. 如何用Android Studio查看build.gradle源码

    上一篇博客里讲过 build.gradle 里的每一行代码基本都是在调用一个方法,既然是这样,我们就可以用 android studio(下面简称as) 去查看它源码的方法注释说明,这样就可以理解每个 ...

  3. android build.gradle(groovy)

    一.build.Gradle 这个 build.Gradle 文件来自 drakeet 大神的 Meizi 项目我直接在代码上加注释,参照着注释看代码就行,是不是发现有很多代码平时都没看见过. //M ...

  4. 1.3.6 详解build.gradle文件——Android第一行代码(第二版)笔记

    不同于Eclipse,Android Studio是采用Gradle来构建项目的.Gradle是一个非常先进的项目构建工具,它使用了一种基于Groovy的领域特定语言(DSL)来声明项目设置. 首先看 ...

  5. Android开发之深入理解Android Studio构建文件build.gradle配置

    摘要: 每周一次,深入学习Android教程,TeachCourse今天带来的一篇关于Android Studio构建文件build.gradle的相关配置,重点学习几个方面的内容:1.applica ...

  6. Android(java)学习笔记126:Android Studio中build.gradle简介

    1.首先我们直接上代码介绍: // Top-level build file where you can add configuration options common to all sub-pro ...

  7. Android(java)学习笔记66:Android Studio中build.gradle简介

    1.首先我们直接上代码介绍: // Top-level build file where you can add configuration options common to all sub-pro ...

  8. Android学习之基础知识二(build.gradle文件详解)

    一.详解build.gradle文件 1.Android Studio是采用Gradle来创建项目的,Gradle是非常先进的构建的项目的工具,基于Groovy领域特定的语言(DSL)来声明项目配置, ...

  9. [Android] 配置build.gradle 动态传参

    (1)一个Android工程中有一个build.gradle是负责Project范围的,而Module中又有各自的build.gradle是专门负责模块的. (2)在Gradle中Task是一等公民, ...

随机推荐

  1. hadoop系列二:HDFS文件系统的命令及JAVA客户端API

    转载请在页首明显处注明作者与出处 一:说明 此为大数据系列的一些博文,有空的话会陆续更新,包含大数据的一些内容,如hadoop,spark,storm,机器学习等. 当前使用的hadoop版本为2.6 ...

  2. Vue.js 系列教程 4:Vuex

    这是关于 JavaScript 框架 Vue.js 五个教程的第四部分.在这一部分,我们会学习使用 Vuex 进行状态管理. 这不是一个完整的指南,而是基础知识的概述,所以你可以了解 Vue.js 以 ...

  3. Spring装配Bean---使用xml配置

    声明Bean Spring配置文件的根元素是<beans>. 在<beans>元素内,你可以放所有的Spring配置信息,包括<bean>元素的声明. 除了Bean ...

  4. selenium框架与chrome浏览器的不兼容问题

    在一次偶然的情况下,在chrome上用selenium框架去抓取某个id为XX的页面元素,使用WebDriver的findElement().click()方法进行点击,原来在firefox浏览器运行 ...

  5. 复制vmware中的centos后无法上网问题

    复制vmware中的centos后无法上网问题 查看IP命令 ip addr 网卡信息 eth1: mtu 1500 qdisc pfifo_fast state UP qlen 1000 使用的是e ...

  6. linux文件和目录权限

    linux系统文件和目录的权限说明 文件权限是Linux系统的第一道安全防线,基本的权限有读取(r).写入(w)和执行(x): 文件访问模式 读取:用户能够读取文件信息,查看文件内容. 写入:用户可以 ...

  7. 简学Python第四章__装饰器、迭代器、列表生成式

    Python第四章__装饰器.迭代器 欢迎加入Linux_Python学习群  群号:478616847 目录: 列表生成式 生成器 迭代器 单层装饰器(无参) 多层装饰器(有参) 冒泡算法 代码开发 ...

  8. Docker存储驱动之Btrfs简介

    简介 Btrfs是下一代的copy-on-write文件系统,它支持很多高级特性,使其更加适合Docker.Btrfs合并在内核主线中,并且它的on-disk-format也逐渐稳定了.不过,它的很多 ...

  9. 每天一个linux命令(32)--/etc/group文件详解

    Linux /etc/group 文件与 /etc/passwd 和/etc/shadow 文件都是有关于系统管理员对用户和用户组管理时相关的文件.Linux /etc/group 文件是有关于系统管 ...

  10. ERP和MES破冰之路 [普实MES升级中国“智”造]

    题记:早在2007年,普实就提出AIO一体化产品概念,全力打造ERP的资源闭环,并取得了良好的市场效应.如今,在制造业的智能生产需求下,生产制造执行系统(MES)成功推向市场. MES是什么? 制造执 ...