本文大部份內容來自 Gradle 官方文檔,英文 OK 的同窗能夠直接看官方文檔。 Gradle 系列文章的示例代碼都放在了 zjxstar 的 GitHub 上了。html
本文假設你們都已經掌握了 Gradle 構建項目的目錄結構。其中,腳本文件 settings.gradle 和 build.gradle 相當重要。Gradle 中的一系列構建操做都基於這兩個文件。java
本系列文章想和你們一塊兒學習 Gradle 的基礎知識,如:Project、Task 和 Transform 等。本文的主要內容是 Project ,其中會涉及到一些簡單的 Task,這裏不會詳細介紹 Task,你們只需知道有 Task 這個概念便可。文中的示例代碼都基於 Android Studio 建立的標準 Android 項目。android
在 Gradle 中,最重要的兩個概念是 Project(項目) 和 Task(任務)。每一次構建都至少包含一個 Project,每個 Project 又包含了一個或多個 Task。每一個 build.gradle 文件都表明一個 Project,其實 Project 能夠理解爲在業務範圍內,被抽象出來的一個個獨立的模塊。而 Task 通常被定義在 build.gradle 中,它表示一個操做,好比:複製文件、打個 jar 包、上傳文件等。git
以 Android 項目舉例說明:github
注:Demo 中使用的 Gradle 版本爲 3.3.1 。閉包
使用 Android Studio 建立項目後,會自動生成兩個模塊,一個是以項目名命名的根模塊,另外一個是 app 模塊。兩個模塊中都有 build.gradle 文件,按照前文的說法,就是兩個 Project。其中,項目 GradleSample 被稱爲 rootProject ,項目 app 被稱爲 subProject 。在根 build.gradle 文件中默認有一個名爲 clean 的 Task,它的職責是刪除根模塊下 build 目錄。app
在初始化構建過程當中,Gradle 會基於 build 腳本文件來組裝 Project 和 Task。ide
執行一個 Gradle 構建的最簡單形式是執行一個 Task,而一些 Task 可能會依賴於其餘 Task。Gradle 爲了管理這些 Task 會在任何一個 Task 執行前構建一個 DAG 圖(Directed Acyclic Graph,有向無環圖)。這意味着全部的 Task 都會被一個接一個地執行,並且只執行一次。那些沒有依賴的 Task 一般會被優先執行。學習
Gradle 的構建生命週期分爲三個階段:gradle
在 Gradle 構建的初始化階段,Gradle 會給每一個項目建立一個 Project 對象。那麼 Project 又具備怎樣的生命週期呢?
Gradle 針對 Project 實例執行項目的構建文件以配置項目。build 腳本中的任何屬性和方法都會委託給關聯的 Project 對象。這意味着,能夠直接在腳本中使用 Project 接口上的任何屬性和方法。
例如:
defaultTasks('some-task') // Delegates to Project.defaultTasks()
reportsDir = file('reports') // Delegates to Project.file() and the Java Plugin
複製代碼
你也能夠經過 Project 實例使用 Project 屬性,好比:
project.name // 獲取project的名字,而不是單獨使用name屬性
複製代碼
你能夠在構建腳本中按照名稱訪問這些屬性,也能夠經過 Project 的
project.property(java.lang.String) // 例如:project.property('version')
複製代碼
方法來進行訪問。
一個項目在搜索屬性時會考慮 5 個屬性範圍:
project.getRootProject()
方法就對應了 rootProject
屬性。至於這些屬性的可讀寫性取決於它們是否認義 getters 或者 setters 方法了。名稱 -> 值
對。定義後,此做用域的屬性是可讀寫的。好比:project.ext.prop1 = 'foo' 。讀寫屬性時,Project 都是按照上述範圍的順序進行查找的,在某個範圍找到屬性後就會返回該屬性。若是沒有找到,會拋出異常。
經常使用的 Project 屬性有:
屬性名 | 做用 |
---|---|
allprojects | 當前項目及其全部子項目的集合 |
buildDir | 當前項目的編譯目錄(自動生成) 默認值 porjectDir/build |
defaultTasks | 當前項目的默認任務的名字集 當前構建沒有提供任務名時會執行這些默認任務 |
group | 當前項目的組名 |
logger | 當前項目的日誌器,能夠用來在 build 文件中寫日誌 |
name | 當前項目的名字 |
parent | 當前項目的父項目 |
path | 當前項目的路徑(絕對路徑) |
project | 當前項目的實例 |
rootProject | 當前項目層次結構中的根項目 |
subprojects | 當前項目的子項目集 |
tasks | 當前項目的任務集 |
version | 當前項目的版本號,默認值:unspecified |
示例:使用 gradlew build 命令便可運行(基於第一小節圖中的 Android 項目)。
// 訪問Project的屬性
// 在app模塊的build.gradle中
println project.group // 打印組名:GradleSample
println version // 打印版本號,默認 unspecified
println project.name // 打印項目名:app
println rootProject.name // 打印根項目的名字:GradleSample
logger.quiet('Test project logger property') // 使用logger
for(String taskName : rootProject.defaultTasks) { // 獲取默認任務
println "defaultTask: $taskName" // 打印:defaultTask: clean
}
println rootProject.ext.hello // 打印額外參數
// 在根build.gradle腳本中
defaultTasks 'clean' // 設置默認Task
ext { // 設置額外參數
hello = 'Welcome to Gradle'
}
複製代碼
一個項目在搜索方法時,也會考慮 5 個範圍:
Task.configure( groovy.lang.Closure )
方法。經常使用的 Project 方法有:
方法名(不列出參數,部分方法有重載) | 做用 |
---|---|
afterEvaluate | 能夠添加一個閉包,它會在項目完成評估後當即執行。 當執行屬於該項目的構建文件時,會通知此類監聽器。 |
allprojects | 配置當前項目以及它的每一個子項目 |
apply | 應用插件或腳本 |
beforeEvaluate | 添加一個閉包,她會在項目開始評估前當即執行 |
configure | 經過閉包配置對象集合 |
copy | 拷貝特定文件 |
file | 解析文件 |
findProperty | 找特定屬性,返回它的值,若是沒有,返回null |
hasProperty | 判斷當前項目有沒有指定屬性 |
project | 獲取指定項目的 project 對象 |
setProperty | 給屬性設置值 |
subprojects | 配置當前項目的全部子項目 |
task | 定義一個任務 |
示例:使用 gradlew -q helloTask 命令運行便可。
// 根build.gradle
allprojects {
// 給全部項目都添加一個任務:helloTask
task helloTask {
doLast { task ->
println "I'm ${task.project.name}"
}
}
}
subprojects {
helloTask { // 給全部子項目中的helloTask任務增長一個doFirst回調
doFirst {
println "I'm the task in sub project, doFirst"
}
}
afterEvaluate { project ->
println "it's after evaluate..."
helloTask.configure {
doLast {
println "configure task after evaluate"
}
}
}
}
// 給全部的子項目(除了app項目)的helloTask配置doLast
configure(subprojects.findAll{ it.name != 'app' }) {
helloTask {
doLast {
println "i am not app module, i configure doLast"
}
}
}
複製代碼
輸出結果:
it's after evaluate...
I'm GradleSample
I'm the task in sub project, doFirst
I'm app
configure task after evaluate
複製代碼
本文的內容很少,詳細介紹了 Gradle 中 Project 的生命週期、屬性和方法。同時,概述了 Gradle 構建項目的三個時期,並提到了 Task 。其實,Gradle 主要仍是圍繞 Task 來運轉的,後續文章咱們將學習 Task 的一系列知識。