请解释Android build.gradle groovy语法

时间:2015-04-06 00:09:37

标签: groovy android-studio gradle android-gradle

以下groovy语法的真正含义是什么?

Gradle文档讲述了build.gradle如何只是 groovy。 Android团队已将默认的build.gradle简化为它看起来不像代码(至少对我而言)。请根据groovy语法解释这是做什么的。例如,Android插件使用的这些全局变量声明是什么?

如果您在解释过程中包含对http://groovy-lang.org/syntax.html的引用,则会获得积分。

apply plugin: 'com.android.application'

android {
    compileSdkVersion 21
    buildToolsVersion "21.1.2"

    defaultConfig {
        applicationId "com.crittercism"
        minSdkVersion 15
        targetSdkVersion 21
        versionCode 5
        versionName "5.0"
    }

}

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

2 个答案:

答案 0 :(得分:5)

您可以将gradle构建脚本视为一些委托给对象的代码,该对象可以响应写入其中的方法调用

该脚本使用了大量的Groovy语法糖,因此删除它们应该如下所示:

apply( [plugin: 'com.android.application'] );

android({
    compileSdkVersion( 21 );
    buildToolsVersion( "21.1.2" );

    defaultConfig({
        applicationId( "com.crittercism" );
        minSdkVersion( 15 );
        targetSdkVersion( 21 );
        versionCode( 5 );
        versionName( "5.0" );
    });
});

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

所以脚本实际上是一堆方法调用:

  • def apply(Map)
  • def android(Closure)
  • def dependencies(Closure)

这个android(Closure)将收到一个闭包,并将其中调用的方法委托给一个可以响应这些方法的对象:

  • def compileSdkVersion(Integer)
  • def buildToolsVersion(String)
  • ...

鉴于此,我们可以解析脚本,将其委托给某个对象,然后执行它。

使用DelegatingBaseScript委派是一种方法(不确定Gradle是否这样做)。这是一个愚蠢的工作版本:

import org.codehaus.groovy.control.CompilerConfiguration

gradleScript = '''
apply plugin: 'com.android.application'

android({
    compileSdkVersion( 21 )
    buildToolsVersion( "21.1.2" )
})'''


class PocketGradle {
  def config = [apply:[]].withDefault { [:] }

  def apply(map) {
    config.apply << map.plugin
  }

  def android(Closure closure) {
    closure.delegate = new Expando(
        compileSdkVersion: { Integer version -> 
          config.android.compileSdkVersion = version 
        },
        buildToolsVersion : { String version ->
          config.android.buildToolsVersion = version
        },
    )
    closure()
  }
}

def compiler = new CompilerConfiguration(scriptBaseClass: DelegatingScript.class.name)

shell = new GroovyShell(this.class.classLoader, new Binding(), compiler)

script = shell.parse gradleScript
script.setDelegate( gradle = new PocketGradle() )
script.run()

assert gradle.config == [
  apply: ['com.android.application'],
  android: [
    compileSdkVersion: 21,
    buildToolsVersion: '21.1.2'
  ]
]

您可以在Groovy Web Console中执行脚本(单击“在控制台中编辑”,然后单击“执行脚本”)。

大多数语法解释都在DSL section

  
      
  1. 命令链
  2.         

    Groovy允许您省略围绕顶级语句的方法调用的参数的括号。 “命令链”功能通过允许我们链接这种无括号的方法调用来扩展它,既不需要围绕参数的括号,也不需要链接调用之间的点。

还有Groovy ConfigSlurper,但我不确定它是否可以像Gradle想要的那样。

答案 1 :(得分:3)

感谢AndroidGuy为我提供了以下信息的优秀视频。视频长达35分钟,所以这里是TL; DR。

此语法大多数是method次调用和closures的混合。闭包用花括号表示。另请注意,方法调用不需要括号。

apply plugin: 'com.android.application'

这是使用单个命名参数“plugin”调用apply对象上的project方法。项目对象是Gradle提供的顶级对象。

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

这是设置项目对象的dependencies属性。 Groovy properties基本上是getter和setter的简写。 dependencies属性是一个委托给DependencyHandler的Closure对象。 Groovy delegation本质上是一种增加闭包范围解析的方法。依赖关系包含一个用于编译的单个方法调用,它接受一个FileTree位置参数。 FileTree由项目对象中定义的fileTree方法生成。编译方法对我来说仍然有点模糊。它似乎来自Java plugin,但没有明确记录在那里。 “编译”部分对我来说仍然有点神奇。

android {
    ...
}

我将把'android'部分作为练习留给读者。网络上没有Android Gradle域特定语言(DSL)。你必须download it