本文通过实例分析验证了 Gradle 中 all、each 的区别
一、官网 api
二、区别
all 是 gradle 中 DomainObjectCollection 接口的方法。
each 是 groovy 中 List、Map 等集合类的方法。
它们的区别:
1.
all 会对集合内现有的元素和之后加入的元素,都执行给定的闭包操作。
each 只会对集合内现有的元素执行给定的闭包操作。
2.
all 接收的闭包,可以直接访问集合内元素的属性和方法。
each 接收的闭包,不能直接访问集合内元素的属性和方法。
原因:
all 接收的闭包是一个配置闭包,集合内元素既会作为参数传给这个闭包,也会被设为闭包的委托对象,这样闭包就可以直接访问委托对象(集合内元素)的属性和方法。
each 接收的是一个普通闭包,集合内元素只会作为参数传给这个闭包。
三、实例
看一个修改生成的 apk 的名字的代码:
android {
applicationVariants.all {
it.outputs.all {
outputFileName = "newName.apk"
}
}
}
这是没问题的,执行 assembleRelease 后,发现文件名称成功被改为了 newName.apk。
现在把 applicationVariants.all
改为 applicationVariants.each
:
android {
applicationVariants.each {
it.outputs.all {
outputFileName = "newName.apk"
}
}
}
再次执行 assembleRelease,发现文件没有被改成 newName.apk。这是因为这时 applicationVariants 内还是空的,没有元素。
再改一下,把 each 操作放进 afterEvaluate
中:
afterEvaluate {
android.applicationVariants.each {
it.outputs.all {
outputFileName = "newName.apk"
}
}
}
再次执行 assembleRelease,发现又成功了。因为 afterEvaluate 代表着 Project 已经配置完成,android.applicationVariants 这时已经有了元素,所以 each 能够访问到。
从这可以看出,all 确实是可以对每个加入的元素都执行闭包操作,而 each 只能对当前已有的元素执行操作。
还没完,我们再改一下,把 it.outputs.all
改为 it.outputs.each
:
afterEvaluate {
android.applicationVariants.each {
it.outputs.each {
outputFileName = "newName.apk"
}
}
}
同步,报错了:
> Could not set unknown property 'outputFileName' for project ':app' of type org.gradle.api.Project.
如果放在 android{} 中
android {
applicationVariants.all {
it.outputs.each {
outputFileName = "newName.apk"
}
}
}
报错就会是这样:
> groovy.lang.MissingPropertyException: Could not set unknown property 'outputFileName' for object of type com.android.build.gradle.internal.api.ApplicationVariantImpl.
在使用 each
时,无法访问 outputFileName 属性,而 all
就可以,这就印证了上面所述的第二点区别。
在 each 里,如果要访问 outputFileName,只能通过 it.outputFileName
来访问:
android {
applicationVariants.all {
it.outputs.each {
it.outputFileName = "newName.apk"
}
}
}
最后,我们来看下改名的最简洁的写法:
android {
applicationVariants.all {
outputs.all {
outputFileName = "newName.apk"
}
}
}