Gradle-構(gòu)建過程&計算build執(zhí)行時長

# 任務(wù)

  • 圖解 Gradle 構(gòu)建的三個階段
  • 監(jiān)聽 Gradle 不同階段的回調(diào);
  • 練習(xí)-計算 build 任務(wù)的執(zhí)行時長;

# Gradle 構(gòu)建過程

下面這張圖是是參考網(wǎng)上的,感覺寫的還不錯。

Gradle構(gòu)建過程

根據(jù)在上圖中所示,Gradle 的構(gòu)建過程主要分為三個階段:

  • 初始化階段
  • 配置階段
  • 執(zhí)行階段

## 監(jiān)聽 Gradle 初始化時機

在這個初始化階段中主要有兩個時機需要關(guān)注:

  • setting.gradle 執(zhí)行結(jié)束的監(jiān)聽
//1.setting.gradle 執(zhí)行結(jié)束的監(jiān)聽
gradle.settingsEvaluated {
    println "settings.gradle 初始化執(zhí)行結(jié)束"
}
  • 參與構(gòu)建的Project對象創(chuàng)建完畢的監(jiān)聽
//2.參與構(gòu)建的Project對象創(chuàng)建完畢的監(jiān)聽
gradle.projectsLoaded {
    Gradle gradle ->
        println "settings.gradle 所有在 settings 中 include 的 Project 都創(chuàng)建完成了"
}

## 監(jiān)聽 Gradle 配置階段時機

在 settings.gradle 中可以配置需要參與構(gòu)建的 project ,并且在初始化階段就已經(jīng)創(chuàng)建好對應(yīng)的 project 實例了。
Gradle 的配置階段就是執(zhí)行每一個 Project 對應(yīng)的 build.gradle 的配置代碼。

下面相關(guān)的API是關(guān)于配置的回調(diào):

  • gradle.beforeProject

表示對每一個 project 在執(zhí)行配置代碼之前都會回調(diào)這個方法。

gradle.beforeProject {
    Project project ->
        println ">>>>>>>>gradle beforeProject " + project.name + " 配置開始前回調(diào)"
}
  • project.beforeEvaluate

當(dāng)前 project在執(zhí)行配置代碼之前的回調(diào)

通過 gradle.afterProject 和 project.afterEvaluate 是差不多一下的。

this.afterEvaluate {
    project ->
        println project.name + " 配置結(jié)束監(jiān)聽"
}
  • gradle.projectsEvaluated

表示所有的 project 都執(zhí)行完對應(yīng)的 build.gradle 的配置代碼,準備要去生成對應(yīng)的 Task 依賴圖。

gradle.projectsEvaluated {
    gradle ->
        println "所有的project都配置完畢了,準備生成Task依賴關(guān)系"
}
  • gradle.taskGraph.whenReady

表示 "task 依賴關(guān)系已經(jīng)生成"

gradle.taskGraph.whenReady {
    TaskExecutionGraph graph ->
        println "task 依賴關(guān)系已經(jīng)生成"
}

## 監(jiān)聽 Gradle 執(zhí)行階段時機

Gradle 在配置階段中會執(zhí)行每一個 project 的 build.gradle 的配置代碼,并且最終生成每一個 Task 任務(wù)的依賴關(guān)系。下面到了執(zhí)行階段就會根據(jù)這個依賴關(guān)系去執(zhí)行對應(yīng)的 Task 任務(wù)。

  • gradle.taskGraph.beforeTask

每一個 Task 任務(wù)執(zhí)行之前回調(diào)

gradle.taskGraph.beforeTask {
    Task task ->
        println "Project[${task.project.name}]--->Task[${task.name}] 在執(zhí)行之前被回調(diào)"
}
  • gradle.taskGraph.afterTask

每一個 task 執(zhí)行之后被回調(diào)

gradle.taskGraph.afterTask {
    task, TaskState taskState ->
        //第二個參數(shù)表示 task 的狀態(tài),是可選的參數(shù)
        println "Project[${task.project.name}]--->Task[${task.name}] 在執(zhí)行完畢,taskState[upToDate:${taskState.upToDate},skipped:${taskState.skipped},executed:${taskState.executed},didWork:${taskState.didWork}]"
}

## Gradle 構(gòu)建執(zhí)行結(jié)束的回調(diào)

  • gradle.buildFinished

當(dāng)所有的任務(wù)執(zhí)行完畢的回調(diào)

gradle.buildFinished {
    BuildResult buildResult ->
        println "構(gòu)建完畢"
}

練習(xí)-計算 build 任務(wù)的執(zhí)行時長

在 Android 中 build 的執(zhí)行是最為復(fù)雜,也是執(zhí)行時間最久的一個 Task ,因為 build 這個任務(wù)依賴了很多其他的任務(wù),第一個被依賴的任務(wù)是 preBuild ,因此我們希望在 preBuild 執(zhí)行之前記錄當(dāng)前的時間戳taskStartTime,在 build 執(zhí)行完畢之后記錄當(dāng)前的時間戳taskEndTime,然后計算兩個時間戳的差值即是 build 任務(wù)的執(zhí)行時長啦。

下面是具體的步驟:

  • 通過 project(":app") 對 app module 單獨配置。
  • 通過 project.afterEvaluate 監(jiān)聽 project 配置完畢。
  • 通過 getBuildTask 獲取 preBuild 和 build 兩個任務(wù)對象。
  • 監(jiān)聽 preBuild.doFirst 得到開始執(zhí)行的時間戳。
  • 監(jiān)聽 build.doLast 得到執(zhí)行完畢的時間戳。
  • 最后得到兩個時間戳的差值即是該任務(wù)的執(zhí)行市場。
  • 執(zhí)行 build 任務(wù)。
//配置 app module
project(":app") {
    Project project ->
        project.afterEvaluate {
            //獲取build task 任務(wù)
            Task buildTask = getBuildTask(project, ":app:build")
            //獲取 preBuild 任務(wù)
            Task preBuildTask = getBuildTask(project, ":app:preBuild")

            def taskStartTime = 0
            def taskEndTime = 0

            //在preBuild task 中追加一個監(jiān)聽獲取在preBuild執(zhí)行之前的時間戳的 action 
            preBuildTask.doFirst {
                taskStartTime = System.currentTimeMillis()
            }
            //在build task 中追加一個監(jiān)聽獲取執(zhí)行完畢的時間戳的 action 
            buildTask.doLast {
                taskEndTime = System.currentTimeMillis()
                println "build task 執(zhí)行時間:${taskEndTime - taskStartTime}"
            }
        }
}

/**
 * 獲取該project對應(yīng)的build任務(wù)
 * @param project
 * @return
 */
Task getBuildTask(Project project, String taskPath) {

    //獲取該project管理task的容器
    TaskContainer taskContainer = project.getTasks()

    //拿到build的Task對象
    Task buildTask = taskContainer.getByPath(taskPath)

    return buildTask
}

執(zhí)行 build 任務(wù)

./gradlew build

記錄于 2018-07-26 晚

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • http://www.itdecent.cn/p/7c288a17cda8 總的來說,Android的系統(tǒng)體系結(jié)...
    燕京博士閱讀 1,415評論 0 6
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,545評論 19 139
  • 語法等 定語:修飾限定名詞的成分。狀語:修飾V.adj.adv.或全句。同位語:對某名詞/詞組做進一步解釋說明。與...
    法雲(yún)閱讀 432評論 0 0
  • 小的時候,家里窮。平日里也就是粗茶淡飯,那時我們吃白面饅頭都還不能放開吃,母親也經(jīng)常會做一些窩窩頭,家里有果園,她...
    陪月亮摘星星閱讀 576評論 23 36
  • 我說過,我一直都是一個淡淡的人,對于感情如此,沒有轟轟烈烈,沒有情深似海。對于懷孕也是如此,沒有那么多思前想后,也...
    saysay閱讀 319評論 0 0

友情鏈接更多精彩內(nèi)容