Gradle 提供的屬性對於延遲組態非常重要。當實作自訂任務或外掛程式時,務必使用這些延遲屬性。

Gradle 使用兩個介面表示延遲屬性
屬性和供應器管理建置腳本中的值和組態。
在此範例中,configuration
是一個 Property<String>
,設定為 configurationProvider
Provider<String>
。configurationProvider
延遲提供值 "Hello, Gradle!"
abstract class MyIntroTask : DefaultTask() {
@get:Input
abstract val configuration: Property<String>
@TaskAction
fun printConfiguration() {
println("Configuration value: ${configuration.get()}")
}
}
val configurationProvider: Provider<String> = project.provider { "Hello, Gradle!" }
tasks.register("myIntroTask", MyIntroTask::class) {
configuration.set(configurationProvider)
}
abstract class MyIntroTask extends DefaultTask {
@Input
abstract Property<String> getConfiguration()
@TaskAction
void printConfiguration() {
println "Configuration value: ${configuration.get()}"
}
}
Provider<String> configurationProvider = project.provider { "Hello, Gradle!" }
tasks.register("myIntroTask", MyIntroTask) {
it.setConfiguration(configurationProvider)
}
了解屬性
Gradle 中的屬性是保存值的變數。它們可以在建置腳本中定義和存取,以儲存檔案路徑、版本號碼或自訂值等資訊。
可以使用 project
物件設定和檢索屬性
// Setting a property
val simpleMessageProperty: Property<String> = project.objects.property(String::class)
simpleMessageProperty.set("Hello, World from a Property!")
// Accessing a property
println(simpleMessageProperty.get())
// Setting a property
def simpleMessageProperty = project.objects.property(String)
simpleMessageProperty.set("Hello, World from a Property!")
// Accessing a property
println(simpleMessageProperty.get())
屬性
-
具有這些類型的屬性是可組態的。
-
Property
擴展了Provider
介面。 -
Property.set(T) 方法為屬性指定一個值,覆寫可能存在的任何值。
-
Property.set(Provider) 方法為屬性的值指定一個
Provider
,覆寫可能存在的任何值。這允許您在組態值之前將Provider
和Property
實例連接在一起。 -
Property
可以通過 factory 方法 ObjectFactory.property(Class) 建立。
了解供應器
供應器是表示可能無法立即取得的值的物件。供應器適用於延遲評估,可用於建模可能隨時間變化或取決於其他任務或輸入的值
// Setting a provider
val simpleMessageProvider: Provider<String> = project.providers.provider { "Hello, World from a Provider!" }
// Accessing a provider
println(simpleMessageProvider.get())
// Setting a provider
def simpleMessageProvider = project.providers.provider { "Hello, World from a Provider!" }
// Accessing a provider
println(simpleMessageProvider.get())
供應器
-
具有這些類型的屬性是唯讀的。
-
Provider.get() 方法傳回屬性的當前值。
-
可以使用 Provider.map(Transformer) 從另一個
Provider
建立Provider
。 -
許多其他類型擴展了
Provider
,並且可以在需要Provider
的任何地方使用。
使用 Gradle 管理的屬性
Gradle 的管理屬性允許您將屬性宣告為抽象 getter(Java、Groovy)或抽象屬性(Kotlin)。
然後 Gradle 會自動為這些屬性提供實作,管理它們的狀態。
屬性可以是可變的,表示它同時具有 get()
方法和 set()
方法
abstract class MyPropertyTask : DefaultTask() {
@get:Input
abstract val messageProperty: Property<String> // message property
@TaskAction
fun printMessage() {
println(messageProperty.get())
}
}
tasks.register<MyPropertyTask>("myPropertyTask") {
messageProperty.set("Hello, Gradle!")
}
abstract class MyPropertyTask extends DefaultTask {
@Input
abstract Property<String> messageProperty = project.objects.property(String)
@TaskAction
void printMessage() {
println(messageProperty.get())
}
}
tasks.register('myPropertyTask', MyPropertyTask) {
messageProperty.set("Hello, Gradle!")
}
或唯讀的,表示它僅具有 get()
方法。唯讀屬性是供應器
abstract class MyProviderTask : DefaultTask() {
final val messageProvider: Provider<String> = project.providers.provider { "Hello, Gradle!" } // message provider
@TaskAction
fun printMessage() {
println(messageProvider.get())
}
}
tasks.register<MyProviderTask>("MyProviderTask") {
}
abstract class MyProviderTask extends DefaultTask {
final Provider<String> messageProvider = project.providers.provider { "Hello, Gradle!" }
@TaskAction
void printMessage() {
println(messageProvider.get())
}
}
tasks.register('MyProviderTask', MyProviderTask)
可變的管理屬性
可變的管理屬性是使用 Property<T>
類型的抽象 getter 方法宣告的,其中 T
可以是任何可序列化類型或完全管理的 Gradle 類型。屬性不得有任何 setter 方法。
以下是一個具有 URI
類型的 uri
屬性的任務類型範例
public abstract class Download extends DefaultTask {
@Input
public abstract Property<URI> getUri(); // abstract getter of type Property<T>
@TaskAction
void run() {
System.out.println("Downloading " + getUri().get()); // Use the `uri` property
}
}
請注意,要使屬性被視為可變的管理屬性,屬性的 getter 方法必須是 abstract
並且具有 public
或 protected
可見性。
屬性類型必須是以下之一
屬性類型 | 注意 |
---|---|
|
其中 |
|
可組態的常規檔案位置,其值是可變的 |
|
可組態的目錄位置,其值是可變的 |
|
類型為 |
|
類型為 |
|
具有 |
|
一個可變的 |
|
一個可變的 |
唯讀的管理屬性 (供應器)
您可以宣告唯讀的管理屬性,也稱為供應器,使用 Provider<T>
類型的 getter 方法。方法實作需要衍生值。例如,它可以從其他屬性衍生值。
以下是一個具有 uri
供應器的任務類型範例,該供應器從 location
屬性衍生而來
public abstract class Download extends DefaultTask {
@Input
public abstract Property<String> getLocation();
@Internal
public Provider<URI> getUri() {
return getLocation().map(l -> URI.create("https://" + l));
}
@TaskAction
void run() {
System.out.println("Downloading " + getUri().get()); // Use the `uri` provider (read-only property)
}
}
唯讀的管理巢狀屬性 (巢狀供應器)
您可以通過為使用 @Nested
註釋的類型添加屬性的抽象 getter 方法來宣告唯讀的管理巢狀屬性。屬性不應具有任何 setter 方法。Gradle 為 getter 方法提供實作,並為屬性建立值。
當自訂類型具有具有相同生命週期的巢狀複雜類型時,此模式非常有用。如果生命週期不同,請考慮改用 Property<NestedType>
。
以下是一個具有 resource
屬性的任務類型範例。Resource
類型也是自訂 Gradle 類型,並定義了一些管理屬性
public abstract class Download extends DefaultTask {
@Nested
public abstract Resource getResource(); // Use an abstract getter method annotated with @Nested
@TaskAction
void run() {
// Use the `resource` property
System.out.println("Downloading https://" + getResource().getHostName().get() + "/" + getResource().getPath().get());
}
}
public interface Resource {
@Input
Property<String> getHostName();
@Input
Property<String> getPath();
}
唯讀的管理 "name" 屬性 (供應器)
如果類型包含一個名為 "name" 的 String
類型的抽象屬性,Gradle 將為 getter 方法提供實作,並使用一個 "name" 參數擴展每個建構子,該參數位於所有其他建構子參數之前。
如果類型是介面,Gradle 將提供一個帶有單個 "name" 參數和 @Inject
語意的建構子。
您可以讓您的類型實作或擴展 Named 介面,該介面定義了這樣一個唯讀的 "name" 屬性
import org.gradle.api.Named
interface MyType : Named {
// Other properties and methods...
}
class MyTypeImpl(override val name: String) : MyType {
// Implement other properties and methods...
}
// Usage
val instance = MyTypeImpl("myName")
println(instance.name) // Prints: myName
使用 Gradle 管理的類型
管理類型是抽象類別或介面,沒有欄位,並且其屬性都是管理的。這些類型的狀態完全由 Gradle 管理。
例如,此管理類型定義為介面
public interface Resource {
@Input
Property<String> getHostName();
@Input
Property<String> getPath();
}
具名管理類型是一種管理類型,此外還具有一個 String
類型的抽象屬性 "name"。具名管理類型特別適用於作為 NamedDomainObjectContainer 的元素類型
interface MyNamedType {
val name: String
}
class MyNamedTypeImpl(override val name: String) : MyNamedType
class MyPluginExtension(project: Project) {
val myNamedContainer: NamedDomainObjectContainer<MyNamedType> =
project.container(MyNamedType::class.java) { name ->
project.objects.newInstance(MyNamedTypeImpl::class.java, name)
}
}
interface MyNamedType {
String getName()
}
class MyNamedTypeImpl implements MyNamedType {
String name
MyNamedTypeImpl(String name) {
this.name = name
}
}
class MyPluginExtension {
NamedDomainObjectContainer<MyNamedType> myNamedContainer
MyPluginExtension(Project project) {
myNamedContainer = project.container(MyNamedType) { name ->
new MyNamedTypeImpl(name)
}
}
}
使用 Java Bean 屬性
有時您可能會看到以 Java bean 屬性樣式實作的屬性。也就是說,它們不使用 Property<T>
或 Provider<T>
類型,而是使用具體的 setter 和 getter 方法(或 Groovy 或 Kotlin 中的相應便利方法)實作。
這種屬性定義樣式在 Gradle 中是舊式的,不建議使用
public class MyTask extends DefaultTask {
private String someProperty;
public String getSomeProperty() {
return someProperty;
}
public void setSomeProperty(String someProperty) {
this.someProperty = someProperty;
}
@TaskAction
public void myAction() {
System.out.println("SomeProperty: " + someProperty);
}
}