Gradle學(xué)習(xí)7——編寫(xiě)和使用自定義Task

學(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)管理饲趋。

參考

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市撤蟆,隨后出現(xiàn)的幾起案子奕塑,更是在濱河造成了極大的恐慌,老刑警劉巖家肯,帶你破解...
    沈念sama閱讀 211,123評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件龄砰,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡讨衣,警方通過(guò)查閱死者的電腦和手機(jī)换棚,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,031評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)反镇,“玉大人圃泡,你說(shuō)我怎么就攤上這事≡赶眨” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,723評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀(guān)的道長(zhǎng)辆亏。 經(jīng)常有香客問(wèn)我风秤,道長(zhǎng),這世上最難降的妖魔是什么扮叨? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,357評(píng)論 1 283
  • 正文 為了忘掉前任缤弦,我火速辦了婚禮,結(jié)果婚禮上彻磁,老公的妹妹穿的比我還像新娘碍沐。我一直安慰自己,他們只是感情好衷蜓,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,412評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布累提。 她就那樣靜靜地躺著,像睡著了一般磁浇。 火紅的嫁衣襯著肌膚如雪斋陪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,760評(píng)論 1 289
  • 那天置吓,我揣著相機(jī)與錄音无虚,去河邊找鬼。 笑死衍锚,一個(gè)胖子當(dāng)著我的面吹牛友题,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播度宦,決...
    沈念sama閱讀 38,904評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼置森,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了凫海?” 一聲冷哼從身側(cè)響起呛凶,我...
    開(kāi)封第一講書(shū)人閱讀 37,672評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎行贪,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體建瘫,經(jīng)...
    沈念sama閱讀 44,118評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,456評(píng)論 2 325
  • 正文 我和宋清朗相戀三年啰脚,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了殷蛇。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片实夹。...
    茶點(diǎn)故事閱讀 38,599評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡粒梦,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出匀们,到底是詐尸還是另有隱情,我是刑警寧澤泄朴,帶...
    沈念sama閱讀 34,264評(píng)論 4 328
  • 正文 年R本政府宣布祖灰,位于F島的核電站钟沛,受9級(jí)特大地震影響夫植,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜详民,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,857評(píng)論 3 312
  • 文/蒙蒙 一沈跨、第九天 我趴在偏房一處隱蔽的房頂上張望由捎。 院中可真熱鬧饿凛,春花似錦、人聲如沸心肪。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,731評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)戴已。三九已至,卻和暖如春糖儡,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背桦沉。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,956評(píng)論 1 264
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留永部,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,286評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像组橄,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子玉工,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,465評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理淘菩,服務(wù)發(fā)現(xiàn),斷路器狭郑,智...
    卡卡羅2017閱讀 134,628評(píng)論 18 139
  • 這篇文章講給大家?guī)?lái)gradle打包系列中的高級(jí)用法-自己動(dòng)手編寫(xiě)gradle插件汇在。我們平常在做安卓開(kāi)發(fā)時(shí),都會(huì)在...
    呆萌狗和求疵喵閱讀 15,975評(píng)論 22 80
  • 1. 概述 Android項(xiàng)目的構(gòu)建過(guò)程是由Gradle插件完成的,Gradle 插件是在Gradle框架的基礎(chǔ)上...
    小蕓論閱讀 8,158評(píng)論 1 42
  • 導(dǎo)語(yǔ): 隨著技術(shù)的發(fā)展羡洁,不管是前端開(kāi)發(fā)、服務(wù)端開(kāi)發(fā)或者是移動(dòng)端開(kāi)發(fā)(移動(dòng)也是前端的一個(gè)分支)中都會(huì)用到自動(dòng)化構(gòu)建工...
    伊始雨深閱讀 3,021評(píng)論 0 4
  • 多久沒(méi)有安靜下來(lái)谤狡,記錄這自己的內(nèi)心卧檐。一切都是安安靜靜墓懂、如此淡然霉囚。 也許是忘性大,也許是沒(méi)有心盈罐,總是這...
    盧新莎子閱讀 259評(píng)論 0 0