Defining tasks

A project has one or more tasks to execute some actions, so a task is made up of actions. These actions are executed when the task is executed. Gradle supports several ways to add actions to our tasks.

We can use the doFirst and doLast methods to add actions to our task, and we can use the left shift operator (<<) as a synonym for the doLast method. With the doLast method or the left shift operator (<<) we add actions at the end of the list of actions for the task. With the doFirst method we can add actions to the beginning of the list of actions. The following script shows how we can use the several methods:

task first {
    doFirst {
        println 'Running first'
    }
}

task second {
    doLast { Task task ->
        println "Running ${task.name}"
    }
}

task third << { taskObject ->
    println 'Running ' + taskObject.name
}

When we run the script, we get the following output:

$ gradle first second third
:first
Running first
:second
Running second
:third
Running third

BUILD SUCCESSFUL

Total time: 2.13 secs

For the task second, we add the action to print out text with the doLast method. The method accepts a closure as an argument. The task object is passed to the closure as a parameter. This means we can use the task object in our actions. In the sample build file, we get the value for the name property of the task and print it to the console.

Maybe it is a good time to look more closely at closures, because they are an important part of Groovy and are used throughout Gradle build scripts. Closures are basically reusable pieces of code that can be assigned to a variable or passed to a method. A closure is defined by enclosing the piece of code between curly brackets ({...}). We can pass one or more parameters to closures. If the closure has only one argument, an implicit parameter, it, can be used to reference the parameter value. We could have written the second task as follows, and the result would still be the same:

task second {
    doLast {
        // Using implicit 'it' closure parameter
        println "Running ${it.name}"  
    }
}

We can also define a name for the parameter and use that name in the code. This is what we did for the tasks second and third, wherein we named the closure parameter task and taskObject respectively. The resulting code is more readable if we define the parameter name explicitly in our closure:

task second {
    doLast { Task task ->
        // Using explicit name 'task' as closure parameter
        println "Running ${task.name}"  
    }
}

Defining actions with the Action interface

Gradle often has more than one way of defining something, as we will see throughout the book. Besides using closures to add actions to a task, we can also use a more verbose way by passing an implementation class of the org.gradle.api.Action interface. The Action interface has one method: execute. This method is invoked when the task is executed. The following piece of code shows a reimplementation of the first task in our build script:

task first {
    doFirst(
        new Action() {
            void execute(task) {
                println "Running ${task.name}"
            }
        }
    )
}

It is good to know that we have choices when we define actions for a task, but the closure syntax is denser and more readable.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.223.237.29