gradle提供了構建生命周期的鈎子來支持執行構建生命周期中某事件發生時想要執行的代碼。一個生命周期事件可能發生在某個構建階段之前、期間或者之后。在執行階段之后發生的生命周期事件是構建的完成。
有兩種方式可以編寫回調生命周期事件:
- 將代碼寫在閉包中
- 實現Gradle API所提供的監聽器接口
具體Gradle提供了哪些鈎子可以通過官方文檔API查看,下面使用與task執行圖有關的鈎子來學習生命周期鈎子的使用。
Task執行圖
在配置階段,gradle決定了在執行階段要運行的task順序。這個順序被建模為一個表示依賴關系的有向無環圖(DAG)。圖中的每個Task被稱為一個節點,且該圖沒有閉環,也就是說先前執行的task不會再次執行。
掛接到task執行圖
Gradle API對task執行圖有對應的領域模型對象,可以通過project.gradle.taskGraph
來訪問task執行圖對象。
- 例子:之前所實現的makeReleaseVersion task,是作為發布task的依賴被自動執行。在了解了生命周期鈎子后,可以編寫一個生命周期鈎子來實現這個makeReleaseVersion task同樣的目標。調用taskGraph的whenReady(Closure)方法,可以在taskGraph生成完成之后執行該方法傳入的閉包。
gradle.taskGraph.whenReady{ TaskExecutionGraph taskGraph ->
if(taskGraph.hasTask(release)) { //查看taskGraph中是否有發布任務
if(!version.release){
version.release = true
ant.propertyfile(file: versionFile) {
entry(key: 'release',type:'string' , operation: '=' , value:'true')
}
}
}
}
實現taskGraph監聽器來掛接
通過監聽器掛接到生命周期需要兩步:
- 編寫一個類來實現特定的監聽器接口
用於監聽taskGraph事件的接口是由TaskExecutionGraphListener接口提供的,其他的事件監聽接口不列舉,用到的時候查閱API。
需要實現TaskExecutionGraphListener接口的graphPopulated(TaskExecutionGraph)方法,具體用法如下:
class ReleaseVersionListener implements TaskExecutionGraphListener{
final static String releaseTaskPath = ':release'
@Override
void graphPopulated(TaskExecutionGraph taskGraph){
if(taskGraph.hasTask(releaseTaskPath)){ //確定release task是否包含在taskGraph中
List<Task> allTasks = taskGraph.allTasks
Task releaseTask = allTask.find{it.path == releaseTaskPath}
Project project = releaseTask.project //通過task來訪問project
if(!project.version.release){
project.version.release = true
project.ant.propertyfile(file: project.versionFile) {
entry(key: 'release',type:'string' , operation: '=' , value:'true')
}
}
}
}
}
在監聽器中不能直接訪問Project實例,但是可以通過GradleAPI,通過task來訪問該task所屬的project。
- 注冊監聽器實現
使用project.gradle.addListener(listener: Object)方法或者project.gradle.taskGraph.addTaskExecutionGraphListener(listener: TaskExecutionGraphListener) 來注冊監聽器,代碼如下
.gradle.taskGraph.addTaskExecutionGraphListener(new TaskExecutionGraphListener())
初始化構建環境
- 初始化腳本:
在目錄<USER>_HOME>/.gradle/init.d
下的以.gradle為擴展名的腳本,會被gradle視為初始化腳本。gradle會在任何構建腳本邏輯解析執行之前運行所有的初始化腳本。在初始化腳本中寫入代碼相當於將代碼掛載到所有的構建生命周期的開始。
- 例子:將插件java應用到構建的根項目中
- 在init.d目錄下創建腳本java.gradle
- 在java.gradle文件中寫入下列代碼
gradle.projectsLoaded{ //選擇使用這個生命周期回調方法來處理這種情況 Gradle gradle -> gradle.rootProject { //由於這是gradle全局腳本,無法訪問項目實例,只能通過GradleAPI來訪問根項目 apply plugin: 'java' } }
一些生命周期時間只有在適當位置生命才會觸發,比如講上面代碼的gradle.projectsLoaded事件生命在build.gradle中則不會被觸發,因為項目加載在初始化階段,而build.gradle文件在配置階段才會處理。