作為一個構(gòu)建腳本的開發(fā)者,你不應(yīng)該局限于編寫任務(wù)動作或者配置邏輯,有時候你想在指定的生命周期事件發(fā)生的時候執(zhí)行一段代碼。生命周期事件可以在指定的生命周期之前、之中或者之后發(fā)生,在執(zhí)行階段之后發(fā)生的生命周期事件就該是構(gòu)建的完成了。
假設(shè)你希望在構(gòu)建失敗時能夠在開發(fā)階段盡早得到反饋,給構(gòu)建生命周期事件添加回調(diào)有兩種方法:一是通過閉包,二是實(shí)現(xiàn)Gradle API的一個監(jiān)聽接口,Gradle并沒有要求你監(jiān)聽生命周期事件,這完全決定于你,通過監(jiān)聽器實(shí)現(xiàn)的優(yōu)勢就是可以給你的類寫單元測試,看看下面這幅圖會有一點(diǎn)直觀的印象:
http://wiki.jikexueyuan.com/project/gradleIn-action/images/dag27.png" alt="" />
在配置階段,Gradle決定在任務(wù)在執(zhí)行階段的執(zhí)行順序,依賴關(guān)系的內(nèi)部結(jié)構(gòu)是通過直接的無環(huán)圖(DAG)來表示的,圖中的每一個任務(wù)稱為一個節(jié)點(diǎn),每一個節(jié)點(diǎn)通過邊來連接,你很有可能通過dependsOn或者隱式的依賴推導(dǎo)來創(chuàng)建依賴關(guān)系。記住DAG圖從來不會有環(huán),就是說一個已經(jīng)執(zhí)行的任務(wù)不會再次執(zhí)行,下面這幅圖將要的展示了這個過程:
http://wiki.jikexueyuan.com/project/gradleIn-action/images/dag28.png" alt="" />
回想一下之前我們實(shí)現(xiàn)的makeReleaseVersion任務(wù)是在release任務(wù)之前執(zhí)行的,我們可以編寫一個生命周期回調(diào)方法來取代之前寫一個任務(wù)來執(zhí)行版本修改任務(wù)。構(gòu)建系統(tǒng)準(zhǔn)確知道在執(zhí)行之前應(yīng)該運(yùn)行哪些任務(wù),你可以查詢?nèi)蝿?wù)圖來查看它是否存在,下面這幅圖展示了訪問任務(wù)執(zhí)行圖的相關(guān)接口:
http://wiki.jikexueyuan.com/project/gradleIn-action/images/dag29.png" alt="" />
接下來我們來添加相應(yīng)的監(jiān)聽方法,下面這段代碼通過調(diào)用whenReady方法來注冊回調(diào)接口,當(dāng)任務(wù)圖創(chuàng)建的時候這個回調(diào)會自動執(zhí)行,你知道這個邏輯會在任何任務(wù)之前執(zhí)行,所以你可以移除makeReleaseVersion任務(wù)。
gradle.taskGraph.whenReady { TaskExecutionGraph taskGraph ->
//檢查任務(wù)圖是否包括release任務(wù)
if(taskGraph.hasTask(release)) {
if(!version.release) {
version.release = true
ant.propertyfile(file: versionFile) {
entry(key: 'release', type: 'string', operation: '=',
value: 'true')
}
}
}
}
你也可以實(shí)現(xiàn)一個監(jiān)聽器來實(shí)現(xiàn)同樣的效果,首先在構(gòu)建腳本中編寫一個實(shí)現(xiàn)指定監(jiān)聽器的類,然后在構(gòu)建中注冊這個實(shí)現(xiàn),監(jiān)聽任務(wù)執(zhí)行圖的接口是TaskExecutionGraphListener,編寫的時候你只需要實(shí)現(xiàn)graphPopulate(TaskExecutionGraph)方法,下圖表示了這個過程:
http://wiki.jikexueyuan.com/project/gradleIn-action/images/dag30.png" alt="" />
下面是編程實(shí)現(xiàn):
class ReleaseVersionListener implements TaskExecutionGraphListener {
final static String releaseTaskPath = ':release'
@Override
void graphPopulated(TaskExecutionGraph taskGraph) {
//查看是否包含release任務(wù)
if(taskGraph.hasTask(releaseTaskPath)) {
List<Task> allTasks = taskGraph.allTasks
//查找release任務(wù)
Task releaseTask = allTasks.find {it.path == releaseTaskPath }
Project project = releaseTask.project
if(!project.version.release) {
project.version.release = true
project.ant.propertyfile(file: project.versionFile) {
entry(key: 'release', type: 'string', operation: '=',
? value: 'true')
}
}
}
}
}
def releaseVersionListener = new ReleaseVersionListener()
//注冊監(jiān)聽器
gradle.taskGraph.addTaskExecutionGraphListener(releaseVersionListener)