Gradle 自動(dòng)化構(gòu)建項(xiàng)目(一)Gradle 核心之生命周期

一、前言
image.png

????從明面上看,Gradle 是一款強(qiáng)大的構(gòu)建工具,但 Gradle 不僅僅是一款強(qiáng)大的構(gòu)建工具,它更像是一個(gè)編程框架。Gradle 的組成可以細(xì)分為如下三個(gè)方面:

????groovy 核心語(yǔ)法:包括 groovy 基本語(yǔ)法、閉包、數(shù)據(jù)結(jié)構(gòu)、面向?qū)ο蟮鹊取?br> Android DSL(build scrpit block):Android 插件在 Gradle 所特有的東西,我們可以在不同的 build scrpit block 中去做不同的事情。
Gradle API:包含 Project、Task、Setting 等等。
可以看到,Gradle 的語(yǔ)法是以 groovy 為基礎(chǔ)的,而且它還有自己獨(dú)有的 API,所以我們可以把 Gradle 認(rèn)作是一款編程框架,利用 Gradle 我們可以在編程中去實(shí)現(xiàn)項(xiàng)目構(gòu)建過(guò)程中的所有需求。想要隨心所欲地使用 Gradle,我們必須提前掌握好 groovy。需要注意的是,Groovy 是一門(mén)語(yǔ)言,而 DSL 一種特定領(lǐng)域的配置文件,Gradle 是基于 Groovy 的一種框架工具,而 gradlew 則是 gradle 的一個(gè)兼容包裝工具。

Gradle 有以下優(yōu)勢(shì):

  • 靈活性:相對(duì)于 Maven、Ant 等構(gòu)建工具,Gradle 提供了一系列的 API 讓我們有能力去修改或定制項(xiàng)目的構(gòu)建過(guò)程。例如我們可以利用 Gradle 去動(dòng)態(tài)修改生成的 APK 包名。
  • 粒度性:使用 Maven、Ant 等構(gòu)建工具時(shí),我們的源代碼和構(gòu)建腳本是獨(dú)立的,而且我們也不知道其內(nèi)部的處理是怎樣的。但是 Gradle 則不同,它從源代碼的編譯、資源的編譯、到生成 APK 的過(guò)程中都是一個(gè)接一個(gè)來(lái)執(zhí)行的。此外,Gradle 構(gòu)建的粒度細(xì)化到了每一個(gè) task 之中。并且它所有的 Task 源碼都是開(kāi)源的,在我們掌握了這一整套打包流程后,我們就可以通過(guò)修改它的 Task 去動(dòng)態(tài)改變其執(zhí)行流程。例如 Tinker 框架的實(shí)現(xiàn)過(guò)程中,它通過(guò)動(dòng)態(tài)地修改 Gradle 的打包過(guò)程生成 APK 的同時(shí),也生成了各種補(bǔ)丁文件。
  • 擴(kuò)展性:Gradle 支持插件機(jī)制,所以我們可以復(fù)用這些插件,就如同復(fù)用庫(kù)一樣簡(jiǎn)單方便。
    兼容性:Gradle 不僅自身功能強(qiáng)大,而且它還能兼容所有的 Maven、Ant 功能,也就是說(shuō),Gradle 吸取了所有構(gòu)建工具的長(zhǎng)處。
    可以看到,Gradle 相比于其它構(gòu)建工具,其好處不言而喻,而其最核心的原因就是因?yàn)?Gradle 是一套編程框架。
二、Gradle 的生命周期

????所謂 Gradle 的生命周期,即 gradle 的執(zhí)行流程,也就是 Gradle 先執(zhí)行什么后執(zhí)行什么。我們看下它的流程圖:
Gradle 的生命周期

可以看到,gradle 的執(zhí)行流程分了 初始化、配置、執(zhí)行 三個(gè)階段,上圖中的 project、task 我們接下來(lái)幾篇會(huì)詳細(xì)介紹。下面我們看看這幾個(gè)階段。


gradle 生命周期分解
2.1 初始化階段

????初始化階段會(huì)讀取根工程中的 setting.gradle 中的 include 信息,確定有多少工程加入構(gòu)建,然后會(huì)為每一個(gè)項(xiàng)目(build.gradle 腳本文件)創(chuàng)建一個(gè)個(gè)與之對(duì)應(yīng)的 Project 實(shí)例,最終形成一個(gè)項(xiàng)目的層次結(jié)構(gòu)。
????與初始化階段相關(guān)的腳本文件是 settings.gradle,而一個(gè) settings.gradle 腳本對(duì)應(yīng)一個(gè) Settings 對(duì)象,我們最常用來(lái)聲明項(xiàng)目的層次結(jié)構(gòu)的 include 就是 Settings 對(duì)象下的一個(gè)方法,在 Gradle 初始化的時(shí)候會(huì)構(gòu)造一個(gè) Settings 實(shí)例對(duì)象,以執(zhí)行各個(gè) Project 的初始化配置。


setting對(duì)象

????此外,在 settings.gradle 文件中,我們可以指定其它 project 的位置,這樣就可以將其它外部工程中的 moudle 導(dǎo)入到當(dāng)前的工程之中了。示例代碼如下所示:

if (useStepMoudle) {
    // 導(dǎo)入其它 App 的 step 步數(shù)模塊
    include "step"
    project(":step").projectDir = new File("../OtherApp/step")
}
2.2 配置階段

????配置階段的任務(wù)是執(zhí)行各項(xiàng)目下的 build.gradle 腳本,完成 Project 的配置,與此同時(shí),會(huì)構(gòu)造 Task 任務(wù)依賴關(guān)系圖以便在執(zhí)行階段按照依賴關(guān)系執(zhí)行 Task而在配置階段執(zhí)行的代碼通常來(lái)說(shuō)都會(huì)包括以下三個(gè)部分的內(nèi)容,如下所示:

  • 1)、build.gralde 中的各種語(yǔ)句。
  • 2)、閉包。
  • 1)、Task 中的配置段語(yǔ)句
    需要注意的是,執(zhí)行任何 Gradle 命令,在初始化階段和配置階段的代碼都會(huì)被執(zhí)行。
2.3 執(zhí)行階段

????在配置階段結(jié)束后,Gradle 會(huì)根據(jù)各個(gè)任務(wù) Task 的依賴關(guān)系來(lái)創(chuàng)建一個(gè)有向無(wú)環(huán)圖,我們可以通過(guò) Gradle 對(duì)象的 getTaskGraph 方法來(lái)得到該有向無(wú)環(huán)圖。并且當(dāng)有向無(wú)環(huán)圖構(gòu)建完成之后,所有 Task 執(zhí)行之前,我們可以通過(guò) whenReady(groovy.lang.Closure) 或者 addTaskExecutionGraphListener(TaskExecutionGraphListener) 來(lái)接收相應(yīng)的通知,其代碼如下所示:

gradle.getTaskGraph().addTaskExecutionGraphListener(new TaskExecutionGraphListener() {
    @Override
    void graphPopulated(TaskExecutionGraph taskExecutionGraph) {

    }
})

然后,Gradle 構(gòu)建系統(tǒng)會(huì)通過(guò)調(diào)用 gradle <任務(wù)名> 來(lái)執(zhí)行相應(yīng)的各個(gè)任務(wù)。

可以看到,整個(gè) Gradle 生命周期的流程包含如下 四個(gè)部分:

  • 首先,解析 settings.gradle 來(lái)獲取模塊信息,這是初始化階段。
  • 然后,配置每個(gè)模塊,配置的時(shí)候并不會(huì)執(zhí)行 task。
  • 接著,配置完了以后,有一個(gè)重要的回調(diào) project.afterEvaluate,它表示所有的模塊都已經(jīng)配置完了,可以準(zhǔn)備執(zhí)行 task 了。
  • 最后,執(zhí)行指定的 task 及其依賴的 task。

????在 Gradle 構(gòu)建命令中,最為復(fù)雜的命令可以說(shuō)是 gradle build 這個(gè)命令了,因?yàn)轫?xiàng)目的構(gòu)建過(guò)程中需要依賴很多其它的 task。這里,我們以 Java 項(xiàng)目的構(gòu)建過(guò)程看看它所依賴的 tasks 及其組成的有向無(wú)環(huán)圖,如下所示:
有向無(wú)環(huán)圖
2.4 生命周期監(jiān)聽(tīng)

????上面我們學(xué)習(xí)了 Gradle 的執(zhí)行生命流程,下面我們?cè)谒谋O(jiān)聽(tīng)回調(diào)中做一些輸出。首先在項(xiàng)目根目錄的 build.gradle 中添加如下監(jiān)聽(tīng)代碼:

//配置階段開(kāi)始前的監(jiān)聽(tīng)回調(diào),也就是初始化階段和配置階段之間
beforeEvaluate {
    println "準(zhǔn)備執(zhí)行配置階段..."
}

//配置階段完成后的監(jiān)聽(tīng)回調(diào),執(zhí)行階段之前的監(jiān)聽(tīng)
afterEvaluate {
    println "配置階段執(zhí)行完畢..."
}

//gradle生命周期執(zhí)行完畢后的回調(diào)監(jiān)聽(tīng)
this.gradle.buildFinished {
    println "執(zhí)行階段執(zhí)行完畢..."
}

this.gradle.beforeProject{
}

this.gradle.afterProject{
}

在根目錄的 setting.gradle 中添加如下代碼:

include ':app'

println "初始化階段開(kāi)始"

接下來(lái)我們執(zhí)行一個(gè)簡(jiǎn)單的 gradle 命令:gradle clean

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

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

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