在本系列的上篇文章中,我们讲到了创建Task的多种方法,在本篇文章中,我们将学习如何读懂Gradle。
Gradle是一种声明式的构建工具。在执行时,Gradle并不会一开始便顺序执行build.gradle文件中的内容,而是分为两个阶段,第一个阶段是配置阶段,然后才是实际的执行阶段。在
配置阶段,Gradle将读取所有build.gradle文件的所有内容来配置Project和Task等,比如设置Project和Task的Property,处理Task之间的依赖关系等。
虽然很多时候我们只需要照着网上的例子写自己的DSL(领域特定语言)语句就行了,但是此时我们所知道的也就只有这么多了。如果我们能够了解Gradle DSL的内部工作机制,那么我们便可以达到
举一反三的效果。在前面的文章中我们讲到,Gradle的DSL只是Groovy语言的内部DSL,也即必须遵循Groovy的语法规则。现在,让我们先来看看以下非常简单的Task:
task showDescription1 << { description = 'this is task showDescription' println description } task showDescription2 << { println description } showDescription2.description = 'this is task showDescription' task showDescription3 << { println description } showDescription3 { description = 'this is task showDescription' }
以上3个Task完成的功能均相同,即先设置Task的description属性,再将其输出到命令行。但是,它们对description的设置方式是不同的。对于showDescription1,我们在定义一个Task的同时
便设置description;对于showDescription2,其本身便是Project的一个Property;而对于showDescription3,我们是在一个和它同名的方法中设置description。
事实上,对于每一个Task,Gradle都会在Project中创建一个同名的Property,所以我们可以将该Task当作Property来访问,showDescription2便是这种情况。另外,Gradle还会创建一个同名的方法,该方法接受一个闭包,我们可以使用该方法来配置Task,showDescription3便是这种情况。
要读懂Gradle,我们首先需要了解Groovy语言中的两个概念,一个Groovy中的Bean概念,一个是Groovy闭包的delegate机制。
Groovy中的Bean和Java中的Bean有一个很大的不同,即Groovy为每一个字段都会自动生成getter和setter,并且我们可以通过像访问字段本身一样调用getter和setter,比如:
class GroovyBeanExample { private String name } def bean = new GroovyBeanExample() bean.name = 'this is name' println bean.name
我们看到,GroovyBeanExample只定义了一个私有的name属性,并没有getter和setter。但是在使用时,我们可以直接对name进行访问,无论是读还是写。事实上,我们并不是
在直接访问name属性,当我们执行"bean.name = 'this is name'"时,我们实际调用的是"bean.setName('this is name')",而在调用"println bean.name"时,我们实际调用的是
"println bean.getName()"。这里的原因在于,Groovy动态地为name创建了getter和setter,采用像直接访问的方式的目的是为了增加代码的可读性,使它更加自然,而在内部,Groovy依然
是在调用setter和getter方法。这样,我们便可以理解上面对showDescription2的description设置原理。
另外,Gradle大量地使用了Groovy闭包的delegate机制。简单来说,delegate机制可以使我们将一个闭包中的执行代码的作用对象设置成任意其他对象。比如:
class Child { private String name } class Parent { Child child = new Child(); void configChild(Closure c) { c.delegate = child c.setResolveStrategy Closure.DELEGATE_FIRST c() } } def parent = new Parent() parent.configChild { name = "child name" } println parent.child.name //child name
在上面的例子中,当我们调用configChild()方法时,我们并没有指出name属性是属于Child的,但是它的确是在设置Child的name属性。事实上光从该方法的调用中,我们根本不知道name是属于哪个对象的,你可能会认为它是属于Parent的。真实情况是,在默认情况下,name的确被认为是属于Parent的,但是我们在configChild()方法的定义中做了手脚,使其不再访问Parent中的name(Parent也没有name属性),而是Child的name。在configChild()方法中,我们将该方法接受的闭包的delegate设置成了child,然后将该闭包的ResolveStrategy设置成了DELEGATE_FIRST。这样,在调用configChild()时,所跟闭包中代码被代理到了child上,即这些代码实际上是在child上执行的。此外,闭包的ResolveStrategy在默认情况下是OWNER_FIRST,即它会先查找闭包的owner(这里即parent),如果owner存在,则在owner上执行闭包中的代码。这里我们将其设置成了DELEGATE_FIRST,即该闭包会首先查找delegate(本例中即child),如果找到,该闭包便会在delegate上执行。对于上面的showDescription3,便是这种情况。当然,实际情况会稍微复杂一点,比如showDescription3()方法会在内部调用showDescription3的configure()方法,再在configure()方法中执行闭包中的代码。
你可能会发现,在使用Gradle时,我们并没有像上面的parent.configChild()一样指明方法调用的对象,而是在build.gradle文件中直接调用task(),apply()和configuration()方法等,这是
因为在没有说明调用对象的情况下,Gradle会自动将调用对象设置成当前Project。比如调用apply()方法和调用project.apply()方法的效果是一样的。查查Gradle的Project文档,你会发现这些方法都是Project类的方法。
另外举个例子,对于configurations()方法(它的作用我们将在后面的文章中讲到),该方法实际上会将所跟闭包的delegate设置成ConfigurationContainer,然后在该ConfigurationContainer上执行闭包中的代码。再比如,dependencies()方法,该方法会将所跟闭包的delegate设置成DependencyHandler。
还有,Project还定义了configure(Object object,Closure configureClosure)方法,该方法是专门用来配置对象的(比如Task),它会将configureClosure的delegate设置成object,之后configureClosure中的执行代码其实是在object上执行的。和Groovy Bean一样,delegate机制的一个好处是可以增加所创建DSL的可读性。
在下一篇文章中,我们将讲到如何进行增量式构建。
相关推荐
例如,使用`kotlin-dsl`可以创建更简洁、易读的Gradle脚本,提高开发效率。 总结来说,"组件化gradle语法参考Demo"涵盖了Gradle在组件化开发中的应用,包括模块配置、依赖管理、构建变体定义、源代码组织以及自定义...
#### 三、settings.gradle示例 假设我们的项目中有两个模块:`app`和`module1`。根据上面的代码逻辑,`settings.gradle`文件可能看起来像这样: ```gradle include ':app' project(':app').projectDir = new File...
除了视频教程之外,阅读官方文档也是深入学习Gradle的重要途径之一。官方文档提供了详尽的信息,包括API参考、用户指南和示例代码,可以帮助你更全面地了解Gradle的功能和用法。 #### 实践项目经验 理论学习固然...
《Groovy学习与Gradle实践经典手册》是一本深度探讨Groovy编程语言和Gradle构建工具的指南,专为Android及Java开发人员提供全面的知识覆盖。本书旨在帮助开发者提升在项目管理和自动化构建方面的技能,使其能够高效...
- **构建配置**:插件允许声明可配置的属性,提供构建的定制化能力,相比直接在`.gradle`文件中编写,实现更加灵活和易读。 ### 3. 插件的实现形式 #### 3.1 脚本插件 脚本插件是一个独立的脚本文件,可以被导入到...
在学习Groovy语法和Gradle配置时,你可以从以下几个方面入手: - **基础语法**:理解Groovy的基本数据类型、流程控制结构、方法定义等。 - **闭包和元编程**:深入学习Groovy的两大特色,掌握闭包的使用场景和元...
Android Studio运行项目时出现 Download https://services.gradle.org/distributions/gradle-3.3-all.zip 21 s 147 ms 是因为这个文件处在外网服务器,下载很慢所以连接总是中断,因此可以自行下载,然后 打开C盘...
### IDEA中Gradle学习指南 #### 一、基本配置 **1.1 环境变量** Gradle的运行依赖于一系列的环境变量配置。最重要的环境变量为`GRADLE_USER_HOME`,它用于指定Gradle项目的缓存路径。通常情况下,这个路径会被...
3. `docs` 或 `documentation` 目录(如果存在):可能包含Gradle的官方文档、API参考和其他学习资源。 4. `LICENSE` 和 `NOTICE` 文件:提供关于Gradle许可和版权信息。 安装Gradle-7.4-bin时,通常会将其解压到...
7. **Groovy DSL 和 Kotlin DSL**:Gradle允许使用Groovy或Kotlin编写构建脚本,提供了直观、简洁的语法。 8. **Task体系**:Gradle的任务系统是其核心,每个任务都有明确的输入和输出,可以自由定义任务间的依赖...
标题中的"gradle合集之gradle5.5.zip"指的是包含了Gradle 5.5版本的完整包,这是一个离线安装包,方便用户在无法或不便从官方网站在线下载时使用。 Gradle 5.5是Gradle发布的一个稳定版本,它包含了许多改进和新...
Git 和 Gradle 入门学习笔记 Git 是一个分布式版本控制系统,Gradle 是一个基于 Apache Ant 和 Maven 的构建自动化工具。在本笔记中,我们将学习如何安装和使用 Git 和 Gradle。 Git 安装 要安装 Git,可以从 ...
`gradle-6.1.1-all.zip`是Gradle的一个特定版本——6.1.1的完整发行版,包含所有必要的组件以供离线使用。 该压缩包`gradle-6.1.1-all.zip`提供了Gradle运行环境,包括GradleWrapper、Gradle CLI(命令行界面)、...
Gradle是一种基于Groovy和Kotlin DSL(领域特定语言)的构建工具,它允许开发者用简洁易读的代码来定义项目构建过程。相比Android Studio早期使用的Ant和后来的Maven,Gradle提供了更加灵活的依赖管理和构建流程定制...
### Android学习系列之Gradle实战 #### 一、Gradle Wrapper 概述 在Android开发过程中,Gradle作为构建工具被广泛使用。然而,在多开发者协作的项目中,不同的开发者可能会使用不同版本的Gradle,这可能导致构建...
Gradle是一个基于JVM的构建工具,是一款通用灵活的构建工具,支持maven, Ivy仓库,支持传递性依赖管理,而不需要远程仓库或者是pom.xml和ivy....文档详细说明的gradle的使用规则以及语法,离线环境下可以学习此文档。
本文侧重于了解自定义properties文件,以及properties中的数据格式,在gradle中如何使用等知识点。 一、概述 在Android Studio 创建一个项目的时候,rootProject下面...又因为Gradle语法可以和Java进行混合使用,所以在
Gradle 8.5版本是这一系列中的一个重要里程碑,它在性能、稳定性和易用性上都有着显著的提升,为开发者带来了更加流畅的构建体验。 一、Gradle的核心概念与优势 1. **基于Groovy的DSL**:Gradle使用Groovy语言作为...
"gradle学习资料2"这个压缩包可能包含一系列的学习资源,如文档、示例代码和教程,帮助用户深入理解Gradle的用法和特性。 1. **Gradle基本概念**: - **构建脚本**:Gradle使用Groovy或Kotlin DSL编写构建脚本,...