標籤:
reference to : http://blog.csdn.net/lzyzsd/article/details/46935405
原文連結
我注意到我在使用Gradle的時候遇到的大多數問題都是和task的執行順序有關的。很明顯如果我的構建會工作的更好如果我的task都是在正確的時候執行。下面我們就深入瞭解一下如何更改task的執行順序。
dependsOn
我認為最直接的方式來說明的你task的執行時依賴別的task的方法就是使用dependsOn方法。
比如下面的情境,已經存在task A,我們要添加一個task B,它的執行必須要在A執行完之後:
這是一個很簡單的情境,假定A和B的定義如下:
task A << {println ‘Hello from A‘}task B << {println ‘Hello from B‘}
只需要簡單的調用B.dependsOn A,就可以了。
這意味著,只要我執行task B,task A都會先執行。
paveldudka$ gradle B:AHello from A:BHello from B
另外,你也可以在task的配置區中來聲明它的依賴:
task A << {println ‘Hello from A‘}task B { dependsOn A doLast { println ‘Hello from B‘ }}
如果我們想要在已經存在的task依賴中插入我們的task該怎麼做呢?
過程和剛才類似。假定已經存在如下的task依賴:
task A << {println ‘Hello from A‘}task B << {println ‘Hello from B‘}task C << {println ‘Hello from C‘}B.dependsOn AC.dependsOn B
加入我們的新的task
task B1 << {println ‘Hello from B1‘}B1.dependsOn BC.dependsOn B1
輸出:
paveldudka$ gradle C:AHello from A:BHello from B:B1Hello from B1:CHello from C
注意dependsOn把task添加到依賴的集合中,所以依賴多個task是沒有問題的。
task B1 << {println ‘Hello from B1‘}B1.dependsOn BB1.dependsOn Q
輸出:
paveldudka$ gradle B1:AHello from A:BHello from B:QHello from Q:B1Hello from B1
mustRunAfter
現在假定我又一個task,它依賴於其他兩個task。這裡我使用一個真實的情境,我有兩個task,一個單元測試的task,一個是UI測試的task。另外還有一個task是跑所有的測試的,它依賴於前面的兩個task。
task unit << {println ‘Hello from unit tests‘}task ui << {println ‘Hello from UI tests‘}task tests << {println ‘Hello from all tests!‘}tests.dependsOn unittests.dependsOn ui
輸出:
paveldudka$ gradle tests:uiHello from UI tests:unitHello from unit tests:testsHello from all tests!
儘管unitest和UI test會子啊test task之前執行,但是unit和ui這兩個task的執行順序是不能保證的。雖然現在來看是按照字母表的順序執行,但這是依賴於Gradle的實現的,你的代碼中絕對不能依賴這種順序。
由於UI測試時間遠比unit test時間長,因此我希望unit test先執行。一個解決辦法就是讓ui task依賴於unit task。
task unit << {println ‘Hello from unit tests‘}task ui << {println ‘Hello from UI tests‘}task tests << {println ‘Hello from all tests!‘}tests.dependsOn unittests.dependsOn uiui.dependsOn unit // <-- I added this dependency
輸出:
paveldudka$ gradle tests:unitHello from unit tests:uiHello from UI tests:testsHello from all tests!
現在unit test會在ui test之前執行了。
但是這裡有個很噁心的問題,我的ui測試其實並不依賴於unit test。我希望能夠單獨的執行ui test,但是這裡每次我執行ui test,都會先執行unit test。
這裡就要用到mustRunAfter了。mustRunAfter並不會添加依賴,它只是告訴Gradle執行的優先順序如果兩個task同時存在。比如我們這裡就可以指定ui.mustRunAfter unit,這樣如果ui task和unit task同時存在,Gradle會先執行unit test,而如果只執行gradle ui,並不會去執行unit task。
task unit << {println ‘Hello from unit tests‘}task ui << {println ‘Hello from UI tests‘}task tests << {println ‘Hello from all tests!‘}tests.dependsOn unittests.dependsOn uiui.mustRunAfter unit
輸出:
paveldudka$ gradle tests:unitHello from unit tests:uiHello from UI tests:testsHello from all tests!
依賴關係如:
mustRunAfter在Gradle2.4中目前還是實驗性的功能。
finalizedBy
現在我們已經有兩個task,unit和ui,假定這兩個task都會輸出測試報告,現在我想把這兩個測試報告合并成一個:
task unit << {println ‘Hello from unit tests‘}task ui << {println ‘Hello from UI tests‘}task tests << {println ‘Hello from all tests!‘}task mergeReports << {println ‘Merging test reports‘}tests.dependsOn unittests.dependsOn uiui.mustRunAfter unitmergeReports.dependsOn tests
現在如果我想獲得ui和unit的測試報告,執行task mergeReports就可以了。
paveldudka$ gradle mergeReports:unitHello from unit tests:uiHello from UI tests:testsHello from all tests!:mergeReportsMerging test reports
這個task是能工作,但是看起來好笨啊。mergeReports從使用者的角度來看感覺不是特別好。我希望執行tests task就可以獲得測試報告,而不必知道mergeReports的存在。當然我可以把merge的邏輯挪到tests task中,但我不想把tests task搞的太臃腫,我還是繼續把merge的邏輯放在mergeReports task中。
finalizeBy來救場了。顧名思義,finalizeBy就是在task執行完之後要執行的task。修改我們的指令碼如下:
task unit << {println ‘Hello from unit tests‘}task ui << {println ‘Hello from UI tests‘}task tests << {println ‘Hello from all tests!‘}task mergeReports << {println ‘Merging test reports‘}tests.dependsOn unittests.dependsOn uiui.mustRunAfter unitmergeReports.dependsOn teststests.finalizedBy mergeReports
現在執行tests task就可以拿到測試報告了:
paveldudka$ gradle tests:unitHello from unit tests:uiHello from UI tests:testsHello from all tests!:mergeReportsMerging test reports
注意,finalizedBy也是Gradle2.4的實驗性功能
[Android Pro] Gradle tip #3-Task順序