Gradle系列相關文章:
1、Gradle理論與實踐一:Gradle入門
2、Gradle理論與實踐二:Groovy介紹
3、Gradle理論與實踐三:Gradle構建腳本基礎
4、Gradle理論與實踐四:自定義Gradle插件
5、Gradle配置subprojects和allprojects的區別:subprojects和allprojects的區別
Gradle構建腳本基礎
Project:根據業務抽取出來的一個個獨立的模塊
Task:一個操作,一個原子性操作。比如上傳一個jar到maven中心庫等
Setting.gradle文件:初始化及整個工程的配置入口
build.gradle文件:
每個Project都會有個build.gradle的文件,是Project構建的入口。Root Project也有一個build.gradle文件,可以獲取到所有的Child Project,並且可以對所有的Child Project進行統一配置:如應用的三方插件、三方依賴庫等。如,我們可以在Root Project的build.gradle文件裏配置:
allprojects {
repositories {
jcenter()
}
}
這樣項目中所有依賴的三方庫都可以在jcenter中下載了,省去了對每個Project去配置的情況。
上面用到的是allprojects,還可以配置subprojects,他們的區別在於:allprojects是對所有project的配置,包括Root Project。而subprojects是對所有Child Project的配置。更詳細的請移步:https://blog.csdn.net/u013700502/article/details/85231687
1、創建一個task
Task的創建方式,可以是:
task hello {
doFirst {
print 'hello:doFirst\n'
}
doLast {
print 'hello:doLast\n'
}
}
也可以是:
tasks.create("hello") {
doFirst {
print 'hello:doFirst'
}
doLast {
print 'hello:doLast'
}
}
他們執行的結果都是一樣的:
bogon:test_gradle mq$ gradle -q hello
hello:doFirst
hello:doLast
task是Project對象的一個函數,原型爲Task create(String name, Closure configureClosure),最後一個參數是閉包的時候,可以放到括號外面,並且括號可以省略,task中的doFirst和doLast分別在任務前後執行。
2、創建Task的幾種方式
- 1、調用Project對象的task(String name)方法,如:
def Task hello = task(hello);
hello << {
print 'hello\n'
}
輸出:
bogon:test_gradle mq$ gradle -q hello
hello
- 2、任務名字+閉包方式,如:
task hello {
description '任務描述'
doLast {
print "方法原型: Task task(String name, Closure configureClosure)\n"
print "任務描述: ${description}"
}
}
輸出結果:
bogon:test_gradle mq$ gradle -q hello
方法原型: Task task(String name, Closure configureClosure)
任務描述: 任務描述
- 3、TaskContainer方式創建:
tasks.create('hello') {
description '任務描述'
doLast {
print "方法原型: Task create(String name, Closure configureClosure)\n"
print "任務描述: ${description}"
}
}
輸出結果:
方法原型: Task create(String name, Closure configureClosure)
任務描述: 任務描述
tasks是Project的屬性,其類型是TaskContainer。其中1和2的創建最終也是調用TaskContainer方式創建的。
3、Task內部執行順序
當我們執行Task的時候,就是執行其擁有的actions列表,是一個List。把Task執行之前、Task本身執行、Task之後執行分別稱爲doFirst、doSelf、doLast,先來看個例子:
def Task hello = task myTask(type: CustomTask);
hello.doFirst {
print 'Task執行之前 do-First\n'
}
hello.doLast {
print 'Task執行之後 do-Last\n'
}
class CustomTask extends DefaultTask {
@TaskAction
def doself() {
print 'Task執行自身 do-self\n'
}
}
輸出:
bogon:test_gradle mq$ gradle -q hello
Task執行之前 do-First
Task執行自身 do-self
Task執行之後 do-Last
通過結果發現確實是按照我們想要的順序執行的。Gradle在執行hello這個任務的時候,Gradle會解析其帶有@TaskAction註解的方法作爲其Task執行的Action,並且把其加入到actionList中。而doFirst、doLast分別會在actionList的最前面和最後面加入,所以之後就達到了按順序執行。
4、Task任務依賴
任務之間是可以有依賴關係的,使用dependsOn執行當前task依賴的任務,如:
task hello << {
print 'hello '
}
task world(dependsOn: hello) {
doLast {
print 'world'
}
}
此時執行gradle -q world
,結果如下:
bogon:test_gradle mq$ gradle -q world
hello world
因爲world任務是依賴hello的,所以當執行world後,先去執行了hello任務,再執行world任務。dependsOn是Task類的一個方法,可以接受多個依賴的任務作爲參數。
修改以下程序:
task hello << {
print 'hello\n'
}
task world(dependsOn: hello) {
doLast {
print 'world\n'
}
}
world.doFirst {
print 'doFirst\n'
}
world.doLast {
print 'doLast2\n'
}
結果:
bogon:test_gradle mq$ gradle -q world
hello
doFirst
world
doLast2
通過結果可以看出,doFirst和doLast可以使用多次,並且按順序執行。doLast可以用 << 操作符替代。
5、自定義屬性
Project和Task允許添加額外自定義屬性,通過對應的ext屬性即可,如
//自定義一個Project的屬性
ext.buildTime = '2018'
//自定義多個屬性
ext {
buildTime = '2018'
month = '12'
}
task time {
doLast {
print "構建時間${buildTime} 年${month}月 \n"
}
}
執行gradle -q time
,執行結果:
bogon:test_gradle mq$ gradle -q time
構建時間2018 年12月
可見我們自定義的屬性正確地取到了,自定義屬性的作用域很廣,只要能得到對應的Project,就能獲取到定義的屬性值。在Android中我們通常使用自定義屬性值來定義我們的版本號、版本名稱等,把這些放到一個單獨的gradle文件中,因爲他們在發版前就會變動,放到單獨的gradle文件中便於管理,在AS根目錄下新建config.gradle如下:
//config.gradle
ext {
android = [
compileSdkVersion: 26,
buildToolsVersion: "25.0.0",
versionName : "6.2.1",
versionCode : 6210,
minSdkVersion : 16,
targetSdkVersion : 23
]
}
在APP對應的build.gradle中取值:
//build.gradle
apply from: rootProject.getRootDir().getAbsolutePath() + '/config.gradle'
compileSdkVersion rootProject.ext.android.compileSdkVersion
buildToolsVersion rootProject.ext.android.buildToolsVersion
就可以獲取到自定義的屬性值。
上例中,除了能獲取到config.gradle中的屬性值,還可以在builg.gradle中調用config.gradle中的方法,具體實現:
//config.gradle
ext {
.......其他.........
//注意方法和屬性寫法的區別
copyApk = this.©Apk
}
def copyApk() {
}
在build.gradle調用:
//build.gradle
apply from: rootProject.getRootDir().getAbsolutePath() + '/config.gradle'
copyApk()
這樣就實現了在build.gradle中調用config.gradle中的copyApk()方法了。