【问题标题】:why does build.gradle doesn't look like Groovy?为什么 build.gradle 看起来不像 Groovy?
【发布时间】:2017-04-26 19:36:01
【问题描述】:

我读到 gradle 是用 groovy 编写的。
但是我的 build.gradle 文件看起来不像 groovy。
事实上,它看起来根本不像一种语言。 这是我的 build.gradle 文件:

apply plugin: 'com.android.application'

android {
    compileSdkVersion 25
    buildToolsVersion "25.0.2"
    defaultConfig {
        applicationId "com.israelkariti.location2_1"
        minSdkVersion 14
        targetSdkVersion 25
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    compile 'com.android.support:appcompat-v7:25.3.1'
    compile 'com.android.support.constraint:constraint-layout:1.0.0-beta4'
    compile 'com.google.android.gms:play-services-maps:10.2.1'
    testCompile 'junit:junit:4.12'
}

谁能给我解释一下这个语法是怎么回事。
该语法如何是 Groovy 代码?
如果我遗漏了一些重要的东西,请详细说明这件事是如何工作的。
谢谢

【问题讨论】:

标签: android android-studio gradle groovy


【解决方案1】:

好吧,Gradle 为其 DSL 添加了一些魔力,但从技术上讲,每个 Gradle 脚本都是完全有效的 Groovy。

要了解dependenciesapply plugin: 等所有内容,我们需要了解不同类型的 Gradle 脚本:

  • 构建脚本 (build.gradle)
  • 设置脚本 (settings.gradle)
  • 初始化脚本(例如init.gradle

所有这些脚本都在不同的范围内执行,因为它们“应用于”不同的对象。 Gradle 将此行为称为“附加委托对象”。

对于构建脚本(就像你问的那个),这个对象是Project。现在让我们分析一下您的 Gradle 脚本:

apply plugin: 'com.android.application'

Project 接口扩展了PluginAware 接口,它定义了一个采用Map<String,?>apply 方法。在 Groovy 中,映射表示法是 [key:value, ...],括号可以省略,String 类型的映射键不写在引号中。所以,plugin: 'com.android.application' 只不过是一个 Groovy 映射并将其交给 apply 方法。

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    ...
}

我将继续这部分并以android 部分结束,因为这样更容易理解:

dependencies 不是 Gradle 关键字,它只是已经提到的Project 接口的方法名称。这个方法需要一个Closure,它被包裹在大括号内。普通方法调用括号再次被省略。闭包在DependencyHandler 对象上执行。现在我们只需将依赖项添加到我们的配置中。我们可以使用add 方法并传递配置名称和依赖表示法(以及可选的新闭包)。

Gradle 魔法从这里开始。对于项目的ConfigurationContainer中的每个现有配置,都会在DependencyHandler中添加一个带有相应配置名称的新方法,因此我们可以简单地使用此方法,而不是一直使用add。在为 Java 开发时,这些配置及其方法是 compileruntimetestCompile(等等)。 fileTree 再次只是Project 接口的一个方法。

android {
    compileSdkVersion 25
    ...
}

Project 接口定义的方法并不是唯一可用的方法。 Gradle 插件(如您正在使用的 Android 插件)可以添加 extensionsconventions。这样,属性和方法可以像属于Project 对象一样被调用。这就是 android 部分可以通过构建脚本中的闭包来配置的方式。

android 闭包中,发生了一些额外的 Gradle 魔法。您可能知道,在 Groovy 中,可以省略 getset 部分并直接访问属性(尽管仍可能调用 getter 或 setter)。 Gradle 还为每个属性添加了一个带有属性名称的方法,可以用作 setter。这样,我们就可以调用compileSdkVersion方法来设置compileSdkVersion属性。再次省略括号。这只是一些语法糖,可以让我们省略赋值运算符。

每当你开始一个新的大括号关卡时,你基本上是使用一个闭包来配置一个对象。有时会创建一个新对象,有时会使用现有属性。有时,您需要阅读文档以了解究竟发生了什么。

【讨论】:

  • 非常感谢。当您说“这只是一些语法糖,它可以让我们省略赋值运算符”时,您的意思是 - 省略括号?用 compileSdkVersion 25 替换 compileSdkVersion(25)
  • Groovy 可让您省略所有“不必要的”括号,这是一种语言功能。所以,是的,您可以感谢 Groovy 编写 compileSdkVersion 25 而不是 compileSdkVersion(25)。但通常,compileSdkVersion 不是一个方法,它是一个属性,所以你可以通过compileSdkVersion = 25 给它赋值。现在 Gradle 会为您生成上述方法,这是一个框架功能,因此您可以省略 = 符号。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-02-21
  • 1970-01-01
  • 2022-01-21
  • 2017-05-11
  • 2018-09-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多