2017-08-17 61 views
1

假設我正在開發一個Gradle插件,並且插件配置的一些任務取決於它如何通過擴展進行配置的輸入。例如:爲什麼PropertyState必需

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 
      } 
     } 
    } 
} 

不幸的是,這不能正常工作。問題是,如果我有一個類似的build.gradle:在那裏我已經指定了一個文件來追蹤

apply plugin: my-plugin 

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

,搖籃將評估在我的任務@InputFileconfig塊運行,因此它會通過查看bad-default.txt而不是file-to-track.txt來確定任務是否是最新的。

推薦的修復程序,這似乎是使用PropertyState像這樣:

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 
      } 
     } 
    } 
} 

這一工程,但它似乎非常冗長和PropertyState東西似乎完全沒有必要。看起來真正的解決方法只是將@InputFile註釋更改爲getter,而不是將其置於屬性上。換句話說,我相信以下效果相同,代碼更少且更易於理解:

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 
      } 
     } 
    } 
} 

通過一些實驗,這似乎具有所需的效果。我錯過了什麼?有沒有什麼時候需要PropertyState

回答

2

問題不在@InputFile進行評估。 @InputFile就在執行任務之前進行評估,所以之後配置階段已經完成,階段階段執行階段。問題PropertyState正在解決的是擴展和任務之間的連線。

讓我們再看看在你的應用方法:

def apply(Project project) { project.with { extensions.create('config', MyConfig) task('printChanges', type: MyTask) { toTrack = config.toTrack } } }

在這裏你:

1)創建於MyConfig類提供的默認值自定義擴展。

2)鏈接價值目前設置在MyConfigMyTask toTrack屬性。

現在看看插件用法:

apply plugin: my-plugin 

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

在這裏你:

1)應用插件(基本上執行插件的應用方法)。

2)重新配置MyConfig#toTrack擴展屬性。

但是,這裏沒有發生什麼,正在更新printChanges任務中的值。這就是PropertyState正在解決的問題。它與任務輸入和輸出評估沒有任何關係。

+1

衛生署!是的,這絕對有道理。在某些時候,我不得不在那裏被用於了最新的檢查是錯誤文件的設置,但如果我強迫任務運行正確的文件進行了處理。這讓我的思想混亂了。這是之前的一些代碼更改,我不確定我是如何設置的。感謝您的澄清。 –

相關問題