學(xué)習(xí)本系列前可以下載相關(guān)的github項(xiàng)目gradleLearnDemo。
地址:https://github.com/sososeen09/gradleLearnDemo
自定義task包含兩個(gè)組件:
1)自定義的task類(lèi)悦屏,封裝了邏輯行為黍析,也被稱(chēng)作任務(wù)類(lèi)型
2)真實(shí)的task卖怜,提供了用于配置行為的task類(lèi)所暴露的屬性值。Gradle把這些task稱(chēng)為增強(qiáng)的task阐枣。
可維護(hù)性是編寫(xiě)自定義task類(lèi)的優(yōu)勢(shì)之一马靠。增強(qiáng)的task的另一個(gè)優(yōu)勢(shì)是可重用性。自定義task所暴露的屬性可以在構(gòu)建腳本中進(jìn)行單獨(dú)設(shè)置蔼两。
我們還是按照之前的例子甩鳄,修改配置文件中的release 參數(shù)。
1 自定義task類(lèi)
前面已經(jīng)提到额划,Gradle為構(gòu)建腳本中每個(gè)簡(jiǎn)單的task都創(chuàng)建了一個(gè)DefaultTask類(lèi)型的實(shí)例妙啃。我們現(xiàn)在創(chuàng)建一個(gè)ReleaseVersionTask,它的作用是把目標(biāo)文件中的release變?yōu)閠rue俊戳。
class ReleaseVersionTask extends DefaultTask{
@Input Boolean release
@OutputFile File destFile
ReleaseVersionTask(){
group='versioning'
description='Makes project a release version.'
}
@TaskAction
void start(){
project.version.release=true;
ant.propertyfile(file:destFile){
entry(key:'release',type:'string',operation:'=',value: 'true')
}
}
}
通過(guò)org.gradle.api.tasks包下的注解可以用來(lái)聲明輸入輸出屬性揖赴。
task輸入驗(yàn)證 @Input注解會(huì)在配置期間驗(yàn)證屬性值。如果值為null抑胎,Gradle會(huì)拋出TaskValidationException異常燥滑。為了允許輸入為null值,可以給它添加@Optional注解阿逃。
2 使用自定義task
我們自定義的task類(lèi)是沒(méi)有辦法自己執(zhí)行的铭拧,要使用和配置自定義task類(lèi)定義的行為和屬性,需要?jiǎng)?chuàng)建一個(gè)增強(qiáng)型的task恃锉。該task定義了它要使用的task類(lèi)型搀菩,在本例中我們定義一個(gè)增強(qiáng)型taskmakeReleaseVersion,它使用的task類(lèi)型是ReleaseVersionTask破托,通過(guò)為它的屬性賦值來(lái)設(shè)置輸入和輸出秕磷。
task makeReleaseVersion(type:ReleaseVersionTask){
// 設(shè)置自定義task屬性
release = version.release
destFile = versionFile
}
執(zhí)行 gradle makeReleaseVersion
命令 ,會(huì)發(fā)現(xiàn)增強(qiáng)型的makeReleaseVersion task與之前的文章中簡(jiǎn)單的task的運(yùn)行結(jié)果表現(xiàn)完全一致炼团。
與簡(jiǎn)單的task實(shí)現(xiàn)相比,增強(qiáng)型task的一個(gè)巨大優(yōu)勢(shì)在于所暴露的屬性可以被單獨(dú)賦值疏尿。
比如瘟芝,ProjectVersion 中的release字段名改為了prodReady,屬性文件改名為 project-version.properties褥琐。
那么makeReleaseVersion task可以這樣設(shè)置
task makeReleaseVersion(type:ReleaseVersionTask){
release = version.prodReady
destFile =file('project-version.properties')
}
3 在buildSrc目錄下構(gòu)建代碼
我們可以把ReleaseVersionTask這個(gè)類(lèi)單獨(dú)放在一個(gè)Groovy文件中锌俱,這樣就可以在其它地方通過(guò)導(dǎo)包的方式來(lái)重用這個(gè)類(lèi)。
在一個(gè)項(xiàng)目工程當(dāng)中敌呈,創(chuàng)建的Groovy類(lèi)適合被移動(dòng)到項(xiàng)目的buildSrc目錄下贸宏。Gradle在buildSrc目錄下使源文件結(jié)構(gòu)標(biāo)準(zhǔn)化造寝。Groovy代碼放在src/main/groovy目錄下,對(duì)于Java文件則是放置在src/main/java目錄下面吭练。位于這些目錄下的文件會(huì)被自動(dòng)編譯诫龙,并且都加入到Gradle構(gòu)建腳本的classpath中。
注意:提取一個(gè)類(lèi)到Groovy文件中需要設(shè)置package鲫咽,在build.gradle中或者其它地方使用這個(gè)類(lèi)的時(shí)候需要導(dǎo)包签赃,這一點(diǎn)與Java類(lèi)的使用是一樣的。當(dāng)然了分尸,如果這個(gè)類(lèi)本身就放在build.gradle中則不需要這個(gè)過(guò)程锦聊,就像之前的例子那樣。
例如 ReleaseVersionTask
package com.sososeen09.gia
import org.gradle.api.DefaultTask
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.OutputFile
import org.gradle.api.tasks.TaskAction
class ReleaseVersionTask extends DefaultTask{
...
}
Groovy文件實(shí)際放置的位置是 buildSrc/src/main/groovy/com/sososeen09/gia/ReleaseVersionTask
根據(jù)同樣的方式箩绍,我們也可以把ProjectVersion這個(gè)類(lèi)抽取出來(lái)孔庭。
使用的時(shí)候,在build.gradle中頂部記得導(dǎo)包:
import com.sososeen09.gia.ReleaseVersionTask
import com.sososeen09.gia.ProjectVersion
...
此時(shí)材蛛,執(zhí)行gradle makeReleaseVersion
命令圆到,我們就可以看到編譯過(guò)程:
:buildSrc:compileJava UP-TO-DATE
:buildSrc:compileGroovy UP-TO-DATE
:buildSrc:processResources UP-TO-DATE
:buildSrc:classes UP-TO-DATE
:buildSrc:jar UP-TO-DATE
:buildSrc:assemble UP-TO-DATE
:buildSrc:compileTestJava UP-TO-DATE
:buildSrc:compileTestGroovy UP-TO-DATE
:buildSrc:processTestResources UP-TO-DATE
:buildSrc:testClasses UP-TO-DATE
:buildSrc:test UP-TO-DATE
:buildSrc:check UP-TO-DATE
:buildSrc:build UP-TO-DATE
Reading the version file
:makeReleaseVersion
記住:buildSrc 目錄被視為Gradle項(xiàng)目的指定路徑仰税。
4 把Task編寫(xiě)的類(lèi)編譯成jar包提供給其它項(xiàng)目使用
我們把Groovy類(lèi)放在了buildSrc目錄下构资,雖然自定義的Task類(lèi)與build.gradle分離開(kāi)了,但是這些類(lèi)依然只能應(yīng)用到當(dāng)前的項(xiàng)目中陨簇。如果我們想要在其它的項(xiàng)目中也可以使用這些Task吐绵,就需要在單獨(dú)的項(xiàng)目中來(lái)定義,然后其它項(xiàng)目通過(guò)聲明依賴(lài)的方式來(lái)使用河绽。
創(chuàng)建一個(gè)新項(xiàng)目己单,把之前我們講的buildSrc目錄下的內(nèi)容復(fù)制到這個(gè)項(xiàng)目中。這個(gè)時(shí)候耙饰,我們就要自己使用Groovy插件來(lái)編譯這些Groovy源代碼了纹笼,就像我們編譯Java代碼需要Java插件一樣。Groovy插件是基于Java插件的苟跪。在這個(gè)項(xiàng)目目錄下新建一個(gè)build.gradle文件廷痘,并在文件中引入Groovy Plugin。
還有一點(diǎn)件已,我們期望把這些Groovy編寫(xiě)的Task和其它類(lèi)打包成jar文件供其它地方使用笋额。這個(gè)時(shí)候我們就可以使用maven插件,把jar文件上傳到repository中篷扩。關(guān)于如何使用maven插件上傳兄猩,可以查閱相關(guān)文檔,也可以看這篇 Gradle User Guide Maven Plugin。為了簡(jiǎn)單演示枢冤,打包的jar文件上傳到了本地的文件系統(tǒng)中鸠姨。最終的build.gradle文件如下:
apply plugin: 'groovy'
apply plugin: 'maven'
version = '1.0'
group = 'com.sososeen09.gia'
archivesBaseName = 'releaseVersionTask'
repositories {
mavenCentral()
}
dependencies {
// 編譯的時(shí)候我們需要使用Gradle中的API
compile gradleApi()
}
uploadArchives {
repositories {
mavenDeployer {
repository(url: "file:../lib")
}
}
}
執(zhí)行gradle uploadArchives
命令后就可以看到,在與當(dāng)前項(xiàng)目同級(jí)的lib文件目錄中生成了我們期望的jar文件淹真。
下面來(lái)演示如何使用這個(gè)jar文件讶迁。我們?cè)傩陆ㄒ粋€(gè)工程,這個(gè)工程中有一個(gè)腳本文件build.gradle和一個(gè)配置文件version.properties趟咆。
其中添瓷,build.gradle中的代碼如下:
import com.sososeen09.gia.ReleaseVersionTask
import com.sososeen09.gia.ProjectVersion
buildscript {
repositories {
maven {
url 'file:../lib'
}
}
dependencies {
classpath 'com.sososeen09.gia:releaseVersionTask:1.0'
}
}
version=new ProjectVersion(0,1)
task printVersion {
doLast{
logger.quiet "Version: $version"
}
}
// Project接口提供了file方法,它會(huì)創(chuàng)建一個(gè)相對(duì)于項(xiàng)目目錄的java.io.File實(shí)例
ext.versionFile=file('version.properties')
task loadVersion{
project.version=readVersion()
}
//readVersion方法值纱,與task是不同的
ProjectVersion readVersion(){
logger.quiet 'Reading the version file'
if(!versionFile.exists()){
throw new GradleException ("Required version file dose not exist:$versionFile.canonicalPath " )
}
//Groovy的文件實(shí)現(xiàn)通過(guò)添加新的方法來(lái)讀取InputStream
Properties versionProps=new Properties()
versionFile.withInputStream{stream->
versionProps.load(stream)
}
// 在Groovy中鳞贷,如果return是方法中的最后一條語(yǔ)句的話(huà),則可以將它省略
new ProjectVersion(versionProps.major.toInteger(),versionProps.minor.toInteger(),versionProps.release.toBoolean())
}
task makeReleaseVersion(type:ReleaseVersionTask){
release = version.release
destFile = versionFile
}
version.properties中的內(nèi)容如下:
major=0
minor=1
release=fasle
執(zhí)行 gradle makeReleaseVersion
命令之后可以看到配置文件中release變?yōu)閠rue虐唠。
5 總結(jié)
通過(guò)以上的介紹搀愧,我們了解了自定義Task的方式。 自定義的Task可以放置在build.gradle腳本中疆偿,也可以在當(dāng)前的項(xiàng)目的buildSrc目錄下咱筛。當(dāng)然了,如果你期望你寫(xiě)的自定義Task可以被其它的項(xiàng)目中使用杆故,那么你可以用一個(gè)單獨(dú)的工程來(lái)放置自定的Task迅箩。
關(guān)于自定義Task的學(xué)習(xí),我們也可以查看Gradle的官方Guide來(lái)查看如何自定義task
下一篇处铛,我們開(kāi)始學(xué)習(xí)Gradle中的依賴(lài)管理饲趋。