溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

gradle中task的作用是什么

發(fā)布時間:2021-08-03 15:47:56 來源:億速云 閱讀:192 作者:Leah 欄目:編程語言

gradle中task的作用是什么,相信很多沒有經(jīng)驗(yàn)的人對此束手無策,為此本文總結(jié)了問題出現(xiàn)的原因和解決方法,通過這篇文章希望你能解決這個問題。

定義task

定義一個task可以有很多種方式,比如下面的使用string作為task的名字:

task('hello') {
    doLast {
        println "hello"
    }
}

task('copy', type: Copy) {
    from(file('srcDir'))
    into(buildDir)
}

還可以使用tasks容器來創(chuàng)建:

tasks.create('hello') {
    doLast {
        println "hello"
    }
}

tasks.create('copy', Copy) {
    from(file('srcDir'))
    into(buildDir)
}

上面的例子中,我們使用tasks.create方法,將新創(chuàng)建的task加到tasks集合中。

我們還可以使用groovy特有的語法來定義一個task:

task(hello) {
    doLast {
        println "hello"
    }
}

task(copy, type: Copy) {
    from(file('srcDir'))
    into(buildDir)
}

tasks 集合類

上面我們在創(chuàng)建task的時候,使用了tasks集合類來創(chuàng)建task。

實(shí)際上,tasks集合類是一個非常有用的工具類,我們可以使用它來做很多事情。

直接在build文件中使用tasks,實(shí)際上是引用了TaskContainer的一個實(shí)例對象。我們還可以使用 Project.getTasks() 來獲取這個實(shí)例對象。

我們看下TaskContainer的定義:

public interface TaskContainer extends TaskCollection<Task>, PolymorphicDomainObjectContainer<Task>

從定義上,我們可以看出TaskContainer是一個task的集合和域?qū)ο蟮募稀?/p>

taskContainer中有四類非常重要的方法:

第一類是定位task的方法,有個分別是findByPath和getByPath。兩個方法的區(qū)別就是findByPath如果沒找到會返回null,而getByPath沒找到的話會拋出UnknownTaskException。

看下怎么使用:

task hello

println tasks.getByPath('hello').path
println tasks.getByPath(':hello').path

輸出:

:hello
:hello

第二類是創(chuàng)建task的方法create,create方法有多種實(shí)現(xiàn),你可以直接通過名字來創(chuàng)建一個task:

task('hello') {
    doLast {
        println "hello"
    }
}

也可以創(chuàng)建特定類型的task:

task('copy', type: Copy) {
    from(file('srcDir'))
    into(buildDir)
}

還可以創(chuàng)建帶參數(shù)的構(gòu)造函數(shù)的task:

class CustomTask extends DefaultTask {
    final String message
    final int number

    [@Inject](https://my.oschina.net/u/4027648)
    CustomTask(String message, int number) {
        this.message = message
        this.number = number
    }
}

上面我們?yōu)镃ustomTask創(chuàng)建了一個帶參數(shù)的構(gòu)造函數(shù),注意,這里需要帶上@javax.inject.Inject注解,表示我們后面可以傳遞參數(shù)給這個構(gòu)造函數(shù)。

我們可以這樣使用:

tasks.create('myTask', CustomTask, 'hello', 42)

也可以這樣使用:

task myTask(type: CustomTask, constructorArgs: ['hello', 42])

第三類是register,register也是用來創(chuàng)建新的task的,不過register執(zhí)行的是延遲創(chuàng)建。也就是說只有當(dāng)task被需要使用的時候才會被創(chuàng)建。

我們先看一個register方法的定義:

TaskProvider<Task> register(String name,
                            Action<? super Task> configurationAction)
                     throws InvalidUserDataException

可以看到register返回了一個TaskProvider,有點(diǎn)像java多線程中的callable,當(dāng)我們調(diào)用Provider.get()獲取task值的時候,才會去創(chuàng)建這個task。

或者我們調(diào)用TaskCollection.getByName(java.lang.String)的時候也會創(chuàng)建對應(yīng)的task。

最后一類是replace方法:

Task replace(String name)
<T extends Task> T replace(String name,
                           Class<T> type)

replace的作用就是創(chuàng)建一個新的task,并且替換掉同樣名字的老的task。

Task 之間的依賴

task之間的依賴關(guān)系是通過task name來決定的。我們可以在同一個項(xiàng)目中做task之間的依賴:

task hello {
    doLast {
        println 'Hello www.flydean.com!'
    }
}
task intro {
    dependsOn hello
    doLast {
        println "I'm flydean"
    }
}

也可以跨項(xiàng)目進(jìn)行task的依賴,如果是跨項(xiàng)目的task依賴的話,需要制定task的路徑:

project('project-a') {
    task taskX {
        dependsOn ':project-b:taskY'
        doLast {
            println 'taskX'
        }
    }
}

project('project-b') {
    task taskY {
        doLast {
            println 'taskY'
        }
    }
}

或者我們可以在定義好task之后,再處理task之間的依賴關(guān)系:

task taskX {
    doLast {
        println 'taskX'
    }
}

task taskY {
    doLast {
        println 'taskY'
    }
}

還可以動態(tài)添加依賴關(guān)系:

task taskX {
    doLast {
        println 'taskX'
    }
}

// Using a Groovy Closure
taskX.dependsOn {
    tasks.findAll { task -> task.name.startsWith('lib') }
}

task lib1 {
    doLast {
        println 'lib1'
    }
}

task lib2 {
    doLast {
        println 'lib2'
    }
}

task notALib {
    doLast {
        println 'notALib'
    }
}

定義task之間的順序

有時候我們的task之間是有執(zhí)行順序的,我們稱之為對task的排序ordering。

先看一下ordering和dependency有什么區(qū)別。dependency表示的是一種強(qiáng)依賴關(guān)系,如果taskA依賴于taskB,那么執(zhí)行taskA的時候一定要先執(zhí)行taskB。

而ordering則是一種并不太強(qiáng)列的順序關(guān)系。表示taskA需要在taskB之后執(zhí)行,但是taskB不執(zhí)行也可以。

在gradle中有兩種order:分別是must run after和should run after。

taskA.mustRunAfter(taskB)表示必須遵守的順序關(guān)系,而taskA.shouldRunAfter(taskB)則不是必須的,在下面兩種情況下可以忽略這樣的順序關(guān)系: 第一種情況是如果shouldRunAfter引入了order循環(huán)的時候。

第二種情況是如果在并行執(zhí)行的情況下,task所有的依賴關(guān)系都已經(jīng)滿足了,那么也會忽略這個順序。

我們看下怎么使用:

task taskX {
    doLast {
        println 'flydean.com'
    }
}
task taskY {
    doLast {
        println 'hello'
    }
}
taskY.mustRunAfter taskX
//taskY.shouldRunAfter taskX

給task一些描述

我們可以給task一些描述信息,這樣我們在執(zhí)行g(shù)radle tasks的時候,就可以查看到:

task copy(type: Copy) {
   description 'Copies the resource directory to the target directory.'
   from 'resources'
   into 'target'
   include('**/*.txt', '**/*.xml', '**/*.properties')
}

task的條件執(zhí)行

有時候我們需要根據(jù)build文件中的某些屬性來判斷是否執(zhí)行特定的task,我們可以使用onlyIf :

task hello {
    doLast {
        println 'www.flydean.com'
    }
}

hello.onlyIf { !project.hasProperty('skipHello') }

或者我們可以拋出StopExecutionException異常,如果遇到這個異常,那么task后面的任務(wù)將不會被執(zhí)行:

task compile {
    doLast {
        println 'We are doing the compile.'
    }
}

compile.doFirst {
    if (true) { throw new StopExecutionException() }
}
task myTask {
    dependsOn('compile')
    doLast {
        println 'I am not affected'
    }
}

我們還可以啟動和禁用task:

myTask.enabled = false

最后我們還可以讓task超時,當(dāng)超時的時候,執(zhí)行task的線程將會被中斷,并且task將會被標(biāo)記為failed。

如果我們想繼續(xù)執(zhí)行,那么可以使用 --continue。

注意, 只有能夠響應(yīng)中斷的task,timeout才有用。

task hangingTask() {
    doLast {
        Thread.sleep(100000)
    }
    timeout = Duration.ofMillis(500)
}

task rule

如果我們想要給某些task定義一些規(guī)則,那么可以使用tasks.addRule:

tasks.addRule("Pattern: ping<ID>") { String taskName ->
    if (taskName.startsWith("ping")) {
        task(taskName) {
            doLast {
                println "Pinging: " + (taskName - 'ping')
            }
        }
    }
}

上我們定義了一個rule,如果taskName是以ping開頭的話,那么將會輸出對應(yīng)的內(nèi)容。

看下運(yùn)行結(jié)果:

> gradle -q pingServer1
Pinging: Server1

我還可以將這些rules作為依賴項(xiàng)引入:

task groupPing {
    dependsOn pingServer1, pingServer2
}

Finalizer tasks

和java中的finally一樣,task也可以指定對應(yīng)的finalize task:

task taskX {
    doLast {
        println 'taskX'
    }
}
task taskY {
    doLast {
        println 'taskY'
    }
}

taskX.finalizedBy taskY

> gradle -q taskX
taskX
taskY

finalize task是一定會被執(zhí)行的,即使上面的taskX中拋出了異常。

看完上述內(nèi)容,你們掌握gradle中task的作用是什么的方法了嗎?如果還想學(xué)到更多技能或想了解更多相關(guān)內(nèi)容,歡迎關(guān)注億速云行業(yè)資訊頻道,感謝各位的閱讀!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI