Gradle创建任务

在研究如何自定义任务之前,我们需要了解一下有关Groovy的概念。了解Groovy的工作原理可以使自定义任务变得更加容易。了解Groovy还可以帮助我们理解Gradle是如何工作的,以及为什么构建配置文件可以按照他们的方式工作。

理解Groovy

简介

Groovy是从Java衍生出来的,运行在Java虚拟机上的敏捷语言。其目标是,不管使作为脚本语言,还是编程语言,都可简单,直接使用。

在Java中,打印字符串到屏幕上,代码如下:

System.out.println(“Hello world!”);

在Groovy中,则通过下面代码来实现:

println ‘Hello world!’
你会注意到以下几个主要不同之处:

  • 没有System.out的命名空间
  • 方法周围没有括号
  • 一行末尾没有分号

这个例子在字符串周围使用了单引号。对于字符串你既可以使用单引号,也可以使用双引号,但他们有不同的用途。双引号字符串可以插入表达式。插值式评估包含占位符的字符串,并通过他们的值替换占位符的过程。这些占位符表达式可以是变量或方法。包含一个方法或多个变量的占位符表达式,需要有$前缀并被花括号包裹。如下:

def name = ‘Andy’
def greeting = “Hello $name!”
def nameSize “Your name is ${name.size()} characters long.”

greeting变量包含字符串“Hello Andy”,nameSize变量包含"Your name is 4 characters long."

字符串插值还允许你动态执行代码。下面这个例子是打印当前日期:

def method = ‘toString’
new Date()."$method"()

在Java中,这种用法看起来会很奇怪,但在动态编程语言中,这是正常的语法。

类和成员变量

在Groovy中创建一个类和Java中创建一个类相似。下面是一个仅包含一个成员变量的类:

class MyGroovyClass{
    String greeting
    
    String getGreeting(){
        return 'hello'
    }
}

注意,无论是类,还是成员变量,都没有明确的访问修饰符。Groovy中默认访问修饰符与Java不同。类和方法一样,是公有的。想使用MyGroovyClass,则需要为它创建一个实例:

def instance = new MyGroovyClass()
instance.greeting 'Hello,Groovy!'
instance.getGreeting()

你可以使用关键字def来创建新的变量。一旦有一个类型的新的实例,你就可以操作它的成员变量了。在Groovy中,访问修饰符是被动添加的。你可以向我们在定义MyGroovyClass中的getGreeting()那样覆盖它。如果没有指定,那么你仍然可以在类中使用每个成员变量的getter和setter方法。

当你试图直接调用一个成员变量时,实际上,你调用的时getter方法。这就意味着你不必输入instance.getGreeting(),可以用跟简单的instance.greeting来代替:

println instance.getGreeting()
println instance.greeting

这两句代码将打印的内容完全相同。

方法

就像使用变量一样,你无需为你的方法定义一个特定的返回类型。但指定返回类型对你来说没任何影响,哪怕仅仅是为了更加清晰。Java和Groovy的另一个不同是,在Groovy中,方法的最后一行通常默认返回,即使没有使用return关键字。
为了演示Java和Groovy之间的差异,我们用下面这个Java例子,返回一个数字的平方:

public int spuare(int num){
return num*num;
}
square(2);

你需要指明该方法是公开访问的,返回类型是什么,参数类型是什么。在方法的结尾,你还需要指定返回值的类型。
同样的方法在Groovy中这样定义的:

def square(def num){
num*num
}
square 4

无论是返回类型,还是参数类型都没有明确定义。这里使用了def关键字,而不是一个明确的类型,在没有使用return关键字的情况下,方法隐晦返回了一个值。然而,为了结构清晰,依然建议使用return关键字。当调用该方法时,不需要括号或分号。

还有另一种利用Groovy来定义新方法的更简短的方式。同样的square方法也可以这样定义:

def spuare ={ num ->
num*num
}

square 8

这不是一个常规的方法,而是一个closure。closure的概念并没有在Java中以相同的方式存在,但它在Groovy和Gradle中发挥了显著的作用。

Closures

Closures时匿名代码块,可以接受参数和返回值。他们可以被是为变量,被当作参数传递给方法。

就像上一个例子一样,你可以在花括号之间添加一段代码块,来简单定义一个clousure。如果想更细点,则还可以添加定义类型,就像下面这样:

Closure square = {
it*it
}
square 16

添加Closure类型可以让每个使用改代码的人都能清楚的知道,一个closure被定义了。前面的例子也引入了内含的未分类参数it的概念。如果你没有明确给closure指定一个参数,则Groovy会自动添加一个。这个参数通常被称为it,你可以在所有的closures中使用它。如果调用者没有指定任何参数,则it为空。it可以让你的代码更简洁,其前提是,closure中只有一个参数。

在Gradle中,我们时时和closures打交道,举个例子,android和dependencies代码块都是closures。

集合

当在Gradle中使用Groovy时,有两个重要的集合类型lists和maps。

在Groovy中创建一个新的list非常容易,无需初始化,像下面这样,即可简单的创建一个list:
List list = [1,2,3,4,5]

迭代一个list也非常的简单,你可以使用each方法来迭代list中的所有元素:

list.each(){element -》
println element
}

each方法是你能够访问list中的每个元素。你可以使用前面提到的it变量,来让代码更加简洁:

list.each(){
println it
}

另外一个集合类型Map.Maps,在Gradle中非常重要,他可以在多个Gradle设置和方法中使用,一个Map就是一个包含所有key-value键值对的列表。你可以这样定义一个map:

Map pizzaPrices = [margherita:10,pepperoni:12]

可使用get方法或方括号来访问map中的特定项目:

pizzaPrices.get("pepperoni)
pizzaPrices[‘pepperoni’]

Groovy也有一个针对该功能的简写。你可以使用点符号来获取map元素,使用key来检索value:

pizzaPrices.pepperoni

Gradle中的Groovy

了解了Groovy基础之后,回过来再看Gradle的构建文件,这使的理解为什么这样配置语法变得更加简单。例如,下面这一行代码,Android插件被应用到构建:

apply plugin: ‘com.android.application’

这段代码完全是Groovy的简写。如果在没有任何简写的情况下,编写它,则会是这样:

project.apply([plugin:‘com.android.application’])

在没有Groovy简写的情况下重写该行,可以清楚的看到apply()是Project类的一个方法,Project类是每个Gradle构建的基础构建代码块。apply需要一个参数,其是一个key为plugin,value为com.android.application的map。

另外一个例子是dependencies代码块。之前,我们定义依赖如下:

dependcies{
compile ‘com.google.code.gson:gson:2.3’
}

现在我们知道该代码块是一个closure,将dependencies()方法传递给Project对象。该closure被传递给一个包含add()方法的DependencyHandler。该方法接收三个参数:一个定义配置的字符串,一个定义依赖标志的对象,一个针对依赖特定属性的closure。当你将完整写出时,应如下所示:

project.dependencies({
add(‘compile’,’'com.google.code.gson:gson:2.3)
}
)

原创文章 63 获赞 59 访问量 4万+

猜你喜欢

转载自blog.csdn.net/u013049016/article/details/92991195