Gradle 为什么需要PropertyState

Gradle 为什么需要PropertyState,gradle,Gradle,假设我正在开发一个Gradle插件,插件配置的一些任务的输入取决于通过扩展配置的方式。例如: class MyTask extends DefaultTask { @InputFile File toTrack @TaskAction def run() { println("The file now contains ${toTrack.text}") } } class MyConfig { File toTrack = n

假设我正在开发一个Gradle插件,插件配置的一些任务的输入取决于通过扩展配置的方式。例如:

class MyTask extends DefaultTask {
    @InputFile
    File toTrack

    @TaskAction
    def run() {
        println("The file now contains ${toTrack.text}")
    }
}

class MyConfig {
    File toTrack = new File('bad-default.txt')
}

class MyPlugin implements Plugin<Project> {
    @Override
    def apply(Project project) {
        project.with {
            extensions.create('config', MyConfig)
            task('printChanges', type: MyTask) {
                toTrack = config.toTrack
            }
        }
     }
}
如果我指定了要跟踪的文件,Gradle将在运行
config
块之前,对我的任务上的
@InputFile
进行评估,因此它将通过查看
bad default.txt
而不是
file to track.txt
来决定任务是否最新

对此建议的修复方法似乎是这样使用:


通过一些实验,这似乎确实达到了预期的效果。我错过了什么?是否有必要使用
PropertyState
的时候?

问题不在于计算
@InputFile
的时间
@InputFile
是在任务执行之前进行评估的,因此在配置阶段完成之后和gradles执行阶段。
PropertyState
正在解决的问题是扩展和任务之间的连接

让我们再看看您的应用方法:


def应用(项目){
计划{
extensions.create('config',MyConfig)
任务('printChanges',类型:MyTask){
toTrack=config.toTrack
}
}
}

给你:

1) 使用
MyConfig
类中提供的默认值创建自定义扩展名

2) 将当前在
MyConfig
中设置的值链接到
MyTask
toTrack属性

现在看看插件的使用情况:

apply plugin: my-plugin

config {
    toTrack = file('file-to-track.txt')
}
给你:

1) 应用插件(基本上执行插件的Apply方法)

2) 重新配置
MyConfig#toTrack
扩展属性


但是这里没有发生的是更新
printChanges
任务中的值。这就是
PropertyState
正在解决的问题。它与任务输入和输出评估无关。

Doh!是的,这绝对有道理。在某个时候,我有一个设置,用于最新检查的文件是错误的,但是如果我强制任务运行,正确的文件就会被处理。这使我的思想混乱不堪。那是几次代码更改之前的事,我不确定我是如何设置的。谢谢你的澄清。
class MyTask extends DefaultTask {
    PropertyState<File> toTrack = project.property(File)

    @InputFile
    File getToTrack { return toTrack.get() }

    @TaskAction
    def run() {
        println("The file now contains ${toTrack.get().text}")
    }
}

class MyConfig {
    private PropertyState<File> toTrack 

    MyConfig(Project project) {
        toTrack = = project.property(File)
        toTrack.set('bad-default.txt')
    }

    void setToTrack(File fileToTrack) { toTrack.set(fileToTrack) }
}

class MyPlugin implements Plugin<Project> {
    @Override
    def apply(Project project) {
        project.with {
            extensions.create('config', MyConfig)
            task('printChanges', type: MyTask) {
                toTrack = config.toTrack
            }
        }
     }
}
class MyTask extends DefaultTask {
    File toTrack

    // This is the only change: put the annotation on a getter
    @InputFile
    File getToTrack() { return toTrack }

    @TaskAction
    def run() {
        println("The file now contains ${toTrack.text}")
    }
}

class MyConfig {
    File toTrack = new File('bad-default.txt')
}

class MyPlugin implements Plugin<Project> {
    @Override
    def apply(Project project) {
        project.with {
            extensions.create('config', MyConfig)
            task('printChanges', type: MyTask) {
                toTrack = config.toTrack
            }
        }
     }
}
apply plugin: my-plugin

config {
    toTrack = file('file-to-track.txt')
}