gradle 里 def 方法为什么不能引用 def 的变量

47 篇文章 0 订阅
31 篇文章 0 订阅

为什么引用不到

在 gradle 中,直接定义一个变量,再定义一个方法,在方法里里是不能引用到该变量的,但在一个闭包中就可以。

def x = 1

def fun() { println x }
fun()

android { println x }

如上图所示,fun 无法引用 x,会报错。

但 android 闭包中的 x 却能打印出来。

这是为什么呢?

由于不知道 gradle 编译后的文件在哪里,这里用 groovy 文件来测试一下,在 android studio 中运行 groovy 程序,可参见我这篇文章

def x = 1

def fun1() { println x }

fun1()

def fun2(Closure closure) { closure() }

fun2 { println x }

运行上面的文件,会报错 Caught: groovy.lang.MissingPropertyException: No such property: x for class: MyGroovy
注释掉 fun1() 后,就可以正常运行。

这跟 gradle 中的现象是一样的。

由于在工具栏上的配置中运行时没有生成 build 文件夹,我们手动执行下 compileGroovy 方法,在 app/build/classes/groovy/main 查看编译后的 MyGroovy.class

核心代码是这样的:

public Object run() {
    Reference x = new Reference(1);
    this.fun1();
    class _run_closure1 extends Closure implements GeneratedClosure {
    }
    return var1[2].callCurrent(this, new _run_closure1(this, x));
}

public Object fun1() {
    CallSite[] var1 = $getCallSiteArray();
    return var1[3].callCurrent(this, var1[4].callGroovyObjectGetProperty(this));
}

public Object fun2(Closure closure) {
    CallSite[] var2 = $getCallSiteArray();
    return var2[5].call(closure);
}

run() 方法就是 groovy 脚本执行的方法。可以看出,它先生成了一个 x 的引用,然后调用 fun1fun2

fun1 调用时,在它的内部执行了 callGroovyObjectGetProperty 方法,在获取 Groovy 对象的属性。也就是在属性中去寻找 x。

fun2 调用时,是将 x 直接传入了闭包的对象。

因为 x 并不是一个属性,只是一个临时变量,所以 fun1 获取不到,而 fun2 能获取到。

怎么引用到

既然是因为属性中没有 x,那我们把 x 加入到属性中就可以了。

看一下 gradle 中一个 project 的属性有哪些。

一个 project 有 6 种属性的作用域:

  1. Project 自己。
  2. 这个 project 的附加属性(通过 ext 定义)。
  3. 通过插件加入到 Project 的 extensions。
  4. 通过插件加入到 Project 的 convention 属性。
  5. 这个 project 里的 task。
  6. 这个 project 的父 project,递归到根 project。从这里访问到的都是只读的。

所以,将 x 的定义放在 ext 中即可:

ext { x = 1 } // 或者 ext.x = 1

def fun() { println x }

fun()

现在能正常打印出 x 的值。

另外,使用 Script 的 binding 对象也可以实现属性中添加 x。

binding.setVariable("x", 1)

def fun() { println x }

fun()
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
是的,Android的build.gradle文件可以读取YAML文件,并将其中的内容用作变量进行配置。以下是一个完整的例子,可以帮助您实现这一目标: 1. 首先,您需要在您的项目根目录下创建一个名为config.yaml的文件,并在其中定义您需要的变量。例如,您可以在config.yaml文件中定义以下内容: ``` # config.yaml app_name: "My Awesome App" version_code: 1 version_name: "1.0.0" ``` 2. 接下来,您需要在build.gradle文件中添加以下代码,以读取config.yaml文件并将其中的内容用作变量: ``` // build.gradle import org.yaml.snakeyaml.Yaml def config = new File("${rootDir}/config.yaml") def yaml = new Yaml().load(config.text) android { defaultConfig { applicationId "com.example.myawesomeapp" minSdkVersion 21 targetSdkVersion 30 versionCode yaml.version_code versionName yaml.version_name } } // You can also use the variables in other parts of your build.gradle file task printAppName { doLast { println "The app name is: ${yaml.app_name}" } } ``` 在上面的代码中,我们使用YAML库来读取config.yaml文件的内容,并将其存储在yaml变量中。然后,我们可以在build.gradle文件的其他部分使用这些变量,例如在defaultConfig块中设置versionCode和versionName属性。 3. 最后,在您的命令行终端中运行以下命令,以确保您的项目可以正确读取config.yaml文件: ``` ./gradlew printAppName ``` 这将运行我们在build.gradle文件中定义的printAppName任务,并输出应用程序名称(即我们在config.yaml文件中定义的“My Awesome App”)。如果输出正确,那么您的项目已经可以正确读取config.yaml文件中的内容,并将其用作变量进行配置。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值