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. In this section, we discuss about the different ways to add actions to a task.

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}" 
    } 
} 
 
// Here we use the << operator 
// as synonym for the doLast method. 
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: 0.592 secs

For the second task, we add the action to print 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 that we can use the task object in our actions. In the sample build file, we get the value for the name property of task and print it to the console.

Maybe it is a good time to look more closely at closures as 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 with curly brackets ({... }). We can pass one or more parameters to the 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. 
        // The type of 'it' is a Gradle task. 
        println "Running ${it.name}" 
    } 
} 

We can also define a name for the parameter and use this name in the code. This is what we did for the second and third tasks; 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, as follows:

task second { 
    doLast { Task task -> 
        // Using explicit name 'task' as closure parameter. 
        // We also defined the type of the parameter. 
        // This can help the IDE to add code completion. 
        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 follows a more verbose way of 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(O 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. We will use closure to configure objects further in this book.

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

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