本節我們從整體的角度來介紹一下Gradle。
一、setting.gradle
在Gradle中,定義了一個設置文件,用於初始化以及工程樹的配置。設置文件的默認的名字就是setting.gradle,此文件位於根工程目錄下。
setting.gradle 的作用就是為了配置子工程。在Gradle中,多工程是通過工程樹表示的,相當於我們在Android Studio下面看到的Project和Module概念一樣。根工程相當於Android Studio的Project,一個根工程可以有多個子工程,也就是很多的Module,這樣就和Android Studio定義的Module概念對應上了。
一個子工程(Module)只有在Setting文件里配置了Gradle才會識別,才會在構建的時候被包含進去。
二、build.gradle
每個Project都會有一個build.gradle文件,該文件是該Project構建的入口,可以在這里針對該Project進行配置,比如配置版本,需要哪些插件,依賴哪些庫等等。
既然每個Project都會有一個build.gradle,那么Root Project可以獲取到所有的Child Project,所以在Root Project的Build文件里面,我們可以對Child Project進行統一的配置,比如應用的插件,依賴的Maven中心庫等等。
例如,我們經常能在Root目錄下的build.gradle文件中看到如下配置:
...
allprojects {
repositories {
google()
jcenter()
}
}
...
這樣配置會非常方便,省去了我們對每個Project都去配置的情況,特別是對於要管理很多的Project的大工程來說。
三、Project 及 Tasks 介紹
在Gradle中,可以有很多Project,你可以定義創建一個Project用於生成一個jar,也可以定義一個另外一個Project用於生成一個war包,還可以定義一個Project用於發布上傳你的war等等。其實在Gradle里面,你可以將Poject理解為在你的業務范圍內,抽象出來的一個個獨立的模塊,你可以根據項目的情況抽象歸類,最后這一個個的Project組成了你的整個Gradle構建。從我們編程的角度來講,它們就是一個個獨立的模塊。好好利用他們,這樣你的代碼就能夠做到低耦合,高內聚。
一個Project里面由包含多個Task,也就是每個Project是由多個Task組成的。那么什么是Task呢?這里我們可以去一個項目的RootProject里面的build.gradle查看,最常見的task如下:
task clean(type: Delete) {
delete rootProject.buildDir
}
具體的含義相信大家都能理解,這里就不過多贅述了。
Task 是一個操作,一個原子性的操作,比如打個jar包,復制一份文件,編譯一次Java代碼,上傳一個jar到Maven中心庫等,這就是一個Task。
四、Task 詳解
1. 創建一個任務(Task)
創建一個任務很簡單,前面很多例子我們也都有演示:
task customTask1 {
doLast {
println 'customTask1:doLast'
}
doFirst {
println 'customTask1:doFirst'
}
}
輸出結果如下:
> Task :customTask1
customTask1:doFirst
customTask1:doLast
這里的Task看着像一個關鍵字,其實它是Project對象的一個函數,原型為create(String name,Closure configureClosure)。customTask1為任務的名字,我們可以自定義,第二個參數是一個閉包,也就是我們花括號里面的代碼塊。
如果了解Groovy的相關知識,我們可以知道,如果最后一個參數是閉包的時候,可以放到括號外面,然后方法的括號可以省略,就生成了上面我們的寫法,很簡潔。該閉包的作用就是用來對我們創建的任務進行配置,例子中我們用了任務的doFirst和doLast方法,分別在任務執行前后輸出一段文字。上面的任務我們還可以改為如下的方式來定義,作用是一樣的:
tasks.create("customTask1") {
doLast {
println 'customTask1:doLast'
}
doFirst {
println 'customTask1:doFirst'
}
}
除此之外,Task還有其他方法和屬性可以使用,需要我們參考Gradle Task的API進一步學習。
2. 任務依賴
Task之間是可以有依賴關系的,這樣我們就可以控制哪些任務先於哪些任務執行;哪些任務執行后,其他任務才能執行。比如,我們運行jar任務之前,compile任務一定要執行過,也就是jar依賴compile。Android 的install任務一定要依賴package任務進行打包生成APK,才能安裝進設備里面。
下面我們來舉一個非常簡單的例子,說明一下:
task outHello {
println 'hello'
}
task outMain(dependsOn: outHello) {
doLast {
println 'main'
}
}
輸出如下:
renhui:android-gradle-book-code renhui$ gradle outMain
> Configure project :
hello
> Task :outMain
main
從例子中,我們可以看出,在創建任務的時候,通過dependsOn可以指定其依賴的任務。
五、自定義屬性
Project 和 Task 都允許用戶添加額外的自定義屬性,要添加額外的自定義屬性,可以使用應用所屬的對應的ext即可實現。添加之后可以通過ext屬性對自定義屬性讀取和設置,如果要同時添加多個自定義屬性,可以通過ext代碼塊:
ext.age = 18
ext {
phone = 123455
address = '保定'
}
task outMain() {
println "年齡是:${age}"
println "電話是:${phone}"
println "年齡是:${address}"
}
輸出結果為:
> Configure project :
年齡是:18
電話是:123455
年齡是:保定
相比局部變量,自定義屬性有更加廣泛的作用域,你可以跨Project,跨Task訪問這些自定義屬性。只要你能訪問這些屬性所屬的對象,你就能訪問到這些屬性。
自定義屬性不僅僅局限在Task和Project上,你可以應用在SourceSet中,這樣等於每種SourceSet多了一個可供配置的屬性。而我們在Android開發中,就經常會用到main SourceSet,當使用productFlavors定義多個渠道的時候,還會新增其他很多的sourceSet。這塊的相關內容,可以在以后的開發過程中多留意和學習使用。