In the Part 1 we talked about tasks and different stages of the build lifecycle. But after I published it I realized that before we jump into Gradle specifics it is very important to understand what we are dealing with - understand its syntax and stop being scared when we see complex build.gradlescripts. With this article I will try to fill this missing gap.

在第一篇博客中,我讲解了关于tasks和构建过程中task的不同阶段。在写完这篇之后,我意识到我应该更详尽的讲述一下Gradle。弄懂语法很重要,免得我们碰到复杂的构建脚本的时候直接晕菜。这篇文章我就会讲解一些语法上的东西。

Syntax

Gradle build scripts are written in Groovy, so before we start analyzing them, I want to touch (briefly) some key Groovy concepts. Groovy syntax is somewhat similar to Java, so hopefully you won't have much problems understanding it.

Gradle脚本是使用Groovy语言来写的。Groovy的语法有点像Java,希望你能接受它。

If you feel comfortable with Groovy - feel free to skip this section.

如果你对Groovy已经很熟悉了,可以跳过这部分了。

There is one important Groovy aspect you need to understand in order to understand Gradle scripts - Closure.

Groovy中有一个很重要的概念你必要要弄懂–Closure(闭包)

Closures

Closure is a key concept which we need to grasp to better understand Gradle. Closure is a standalone block of code which can take arguments, return values and be assigned to a variable. It is some sort of a mix between Callable interface, Future, function pointer, you name it..

Closure是我们弄懂Gradle的关键。Closure是一段单独的代码块,它可以接收参数,返回值,也可以被赋值给变量。和Java中的Callable接口,Future类似,也像函数指针,你自己怎么方便理解都好。

Essentially this is a block of code which is executed when you call it, not when you create it. Let's see a simple Closure example:

关键是这块代码会在你调用的时候执行,而不是在创建的时候。看一个Closure的例子:

def myClosure = { println 'Hello world!' }

//execute our closure
myClosure() #output: Hello world!

Or here is a closure which accepts a parameter:

下面是一个接收参数的Closure:

def myClosure = {String str -> println str }

//execute our closure
myClosure('Hello world!') #output: Hello world!

Or if closure accepts only 1 parameter, it can be referenced as it:

如果Closure只接收一个参数,可以使用it来引用这个参数:

def myClosure = {println it }

//execute our closure
myClosure('Hello world!') #output: Hello world!

Or if closure accepts multiple input parameters:

接收多个参数的Closure:

def myClosure = {String str, int num -> println "$str : $num" }

//execute our closure
myClosure('my string', 21) #output: my string : 21

By the way, argument types are optional, so example above can be simplified to:

另外,参数的类型是可选的,上面的例子可以简写成这样:

def myClosure = {str, num -> println "$str : $num" }

//execute our closure
myClosure('my string', 21) #output: my string : 21

One cool feature is that closure can reference variables from the current context (read class). By default, current context - is the class within this closure was created:

很酷的是Closure中可以使用当前上下文中的变量。默认情况下,当前的上下文就是closure被创建时所在的类:

def myVar = 'Hello World!'
def myClosure = {println myVar}
myClosure() #output: Hello world!

Another cool feature is that current context for the closure can be changed by callingClosure#setDelegate(). This feature will become very important later:

另外一个很酷的点是closure的上下文是可以改变的,通过Closure#setDelegate()。这个特性非常有用:

def myClosure = {println myVar} //I'm referencing myVar from MyClass class
MyClass m = new MyClass()
myClosure.setDelegate(m)
myClosure() class MyClass {
def myVar = 'Hello from MyClass!'
} #output: Hello from MyClass!

As you can see, at the moment when we created closure, myVar variable doesn't exist. And this is perfectly fine - it should be present in the closure context at the point when we execute this closure.

正如你锁看见的,在创建closure的时候,myVar并不存在。这并没有什么问题,因为当我们执行closure的时候,在closure的上下文中,myVar是存在的。

In this case I modified current context for the closure right before I executed it, so myVar is available.

这个例子中。因为我在执行closure之前改变了它的上下文为m,因此myVar是存在的。

Pass closure as an argument

The real benefit of having closures - is an ability to pass closure to different methods which helps us to decouple execution logic.

closure的好处就是可以传递给不同的方法,这样可以帮助我们解耦执行逻辑。

In previous section we already used this feature when passed closure to another class instance. Now we will go through different ways to call method which accepts closure:

前面的例子中我已经展示了如何把closure传递给一个类的实例。下面我们将看一下各种接收closure作为参数的方法:

  1. method accepts 1 parameter - closure (只接收一个参数,且参数是closure的方法)

    myMethod(myClosure)

  2. if method accepts only 1 parameter - parentheses can be omitted (如果方法只接收一个参数,括号可以省略)

    myMethod myClosure

  3. I can create in-line closure (可以使用内联的closure)

    myMethod {println 'Hello World'}

  4. method accepts 2 parameters (接收两个参数的方法)

    myMethod(arg1, myClosure)

  5. or the same as '4', but closure is in-line (和4类似,单数closure是内联的)

    myMethod(arg1, { println 'Hello World' })

  6. if last parameter is closure - it can be moved out of parentheses (如果最后一个参数是closure,它可以从小括号从拿出来)

    myMethod(arg1) { println 'Hello World' }

At this point I really have to point your attention to example #3 and #6. Doesn't it remind you something from gradle scripts?

Gradle tip #2: understanding syntax的更多相关文章

  1. [Android Pro] Gradle tip #3-Task顺序

    reference to : http://blog.csdn.net/lzyzsd/article/details/46935405 原文链接 我注意到我在使用Gradle的时候遇到的大多数问题都是 ...

  2. Gradle tip #3: Tasks ordering

    I noticed that the quite often problem I face when I work with Gradle - is tasks ordering (either ex ...

  3. Gradle tip #1: tasks

    With this post I would like to start series of Gradle-related topics I wish I knew when I first star ...

  4. Gradle基本知识点与常用配置

    查看原文:http://blog.csdn.net/u010818425/article/details/52268126 本文篇幅较长,文中系统地讲解了Gradle的基本知识点以及一些常用的命令和配 ...

  5. Android项目中如何用好构建神器Gradle?(转)

    最近在忙团队并行开发的事情,主要是将各个团队的代码分库,一方面可以降低耦合,为后面模块插件化做铺垫,另一方面采用二进制编译,可以加快编译速度.分库遇到了一些问题,很多都要通过Gradle脚本解决,所以 ...

  6. Android Gradle 构建工具(Android Gradle Build Tools)是什么?

    转载地址:http://mrfu.me/android/2015/07/17/New_Android_Gradle_Build_Tools/ 译者地址:[翻]一览新的 Android Gradle 构 ...

  7. 一览新的 Android Gradle 构建工具:新的 DSL 结构 和 Gradle 2.5

    译者地址:[翻]一览新的 Android Gradle 构建工具:新的 DSL 结构 和 Gradle 2.5 原文:First Look at New Android Gradle Build To ...

  8. javascript——语法 && 结构

    原文链接:Understanding Syntax and Code Structure

  9. Javescript——变量声明的区别

    原文链接:ES6 Syntax and Feature Overview View on GitHub Keyword Scope Hoisting Can Be Reassigned Can Be ...

随机推荐

  1. iOS多线程-05-多图下载

    效果图 常见问题及解决方法 图片重复下载 将内存保存在内存或沙盒中. 若下载的图片量较大,则会出现UI界面不流畅的现象 在子线程中执行下载操作,然后回到主线程成中进行UI界面的刷新. 由于cell的循 ...

  2. [转载] 数据测试常用的Data Profiling方法

    现在对数据质量的要求越来越高,面对一个动辄上亿条数据的报表如何快速对它的数据质量做出分析呢?给大家分享下我们测试时用到的Data Profiling方法. Data Profiling,可以大概翻译“ ...

  3. PS网页设计教程XXX——在PS中创建一个漫画书主题网页布局

    作为编码者,美工基础是偏弱的.我们可以参考一些成熟的网页PS教程,提高自身的设计能力.套用一句话,“熟读唐诗三百首,不会作诗也会吟”. 本系列的教程来源于网上的PS教程,都是国外的,全英文的.本人尝试 ...

  4. Oracle-创建服务器参数文件

    允许使用传统的init.ora或SPFILE作为配置文件.但是建议所有数据库创建和使用一个SPFILE.可以从init.ora创建SPFILE SQL> CREATE spfile FROM p ...

  5. 烂泥:U盘安装Centos6.5

    本文由秀依林枫提供友情赞助,首发于烂泥行天下. 使用U盘安装Centos6.5,需要以下几个步骤: 1. 制作U盘linux系统 2. 设置服务器BIOS 3. 安装Centos,注意引导分区的安装 ...

  6. Python HeapSort

    __author__ = 'student' print 'hello world hello python' ''' heap sort root leftchild 2n+1 rightchild ...

  7. 2016开发一个app需要多少钱?app开发需要哪些成本-app开发问题汇总-广州达到信息

    作为一个APP开发从业者,被外行的朋友们问及最多的问题是,"做一个网站需要多少钱?"或者"开发一个APP需要多少钱?".作为开发过完整网站项目和手机APP的人, ...

  8. runv kill 流程分析

    1.runv/kill.go Action: func(context *cli.Context) 该函数做的工作很简单,就是通过grpc客户端,发送一个grpc请求而已,如下: c.Signal(n ...

  9. react webpack.config.js 入门学习

    在学习react 的时候必然会用到webpack打包工具,webpack的快速入门另外一篇文章中有记录,这里只记录webpack.config.js文件,因为每个项目下都必须配置,通俗的讲,它的作用就 ...

  10. java8-1 final

    1.final可以修饰类,方法,变量 特点: final可以修饰类,该类不能被继承. final可以修饰方法,该方法不能被重写.(覆盖,复写) final可以修饰变量,该变量不能被重新赋值.因为这个变 ...