1, Create tasks in multiple ways
1. Create task with task name
- Example:
// Create task with task name def Task taskCreatedByName = task taskCreatedByName // def Task taskCreatedByName = task(taskCreatedByName) taskCreatedByName.doLast { println "This is a task created by task name" }
- Prototype:
Task task(String name) throws InvalidUserDataException;
2. Create a task with the task name and the Map object configured for the task
- Example:
// Create a task with the task name and the Map object configured for the task def Task taskCreatedByNameAndMap = task taskCreatedByNameAndMap,group:BasePlugin.BUILD_GROUP taskCreatedByNameAndMap.doLast { println "This is a task configuration by task name and Map Object creation task" }
- Prototype:
Task task(Map<String, ?> args, String name) throws InvalidUserDataException;
- Available configurations for Map objects
Configuration item | describe | Default value |
---|---|---|
type | Create based on an existing Task, which is similar to inheritance | DefaultTask |
overwrite | Replace the existing Task and use it with type | false |
dependsOn | Configure task dependencies | [] |
action | An Action or closure added to the task | null |
description | Description of the configuration task | null |
group | Configure grouping of tasks | null |
3. Create a task with the task name and closure configuration
- There are limited items that can be configured through Map objects, so tasks can be configured more flexibly and comprehensively in the form of closures
- Example:
// Create a task with the task name and closure configuration task taskCreatedByNameAndClosure { doLast { println "This is a task created by task name and closure configuration" } }
- Prototype:
Task task(String name, Closure configureClosure);
4. Create a task with task name, Map parameters and closure configuration
- Example:
// Create a task with task name, Map object and closure configuration task taskCreatedByNameMapAndClosure,group:BasePlugin.BUILD_GROUP,{ doLast { println "This is a task name, Map Object and closure configuration creation task" } }
- Prototype:
Task task(Map<String, ?> args, String name, Closure configureClosure);
5. create method of taskcontainer object
- There are also many ways to create tasks using TaskContainer objects. You can view project Look at the different creation methods of java files. Here is only one example
- Example:
// The create method of the TaskContainer object creates a task tasks.create('taskCreatedByTaskContainer') { doLast { println "This is a pass TaskContainer Object creation task" } }
- Prototype:
Task create(String name, Closure configureClosure) throws InvalidUserDataException;
2, Multiple ways to access tasks
1. Access the task by task name
The tasks we create will become an attribute of Project. The attribute name is the task name, so you can access the operation task through the task name
task task1 task1.doLast { println "Access task by task name" }
2. Access tasks by accessing collection elements
Tasks are created through the TaskContainer object in project Tasks in Java is the object of TaskContainer, so you can get the corresponding tasks through tasks
"[]" in the sample code does not mean that tasks is a Map, but that Groovy overloads this operator. Follow up the source code and you will find that it is finally implemented by the called findByName(String name)
task task2 // TaskContainer getTasks(); tasks['task2'].doLast { println "Access tasks by accessing collection elements" }
3. Access via path
There are two ways to access by path: get and find
Difference: get throws an exception when it cannot find a task, while find returns null when it cannot find a task
task task3 tasks['task3'].doLast { println "-----Access tasks via path-----" println tasks.findByPath(':task2') println tasks.getByPath(':task2') println tasks.findByPath(':task0') println tasks.getByPath(':task0') }
// TaskContainer.java @Nullable Task findByPath(String path); Task getByPath(String path) throws UnknownTaskException;
4. Access by name
There are two ways to access by name: get and find
Difference: get throws an exception when it cannot find a task, while find returns null when it cannot find a task
task task4 tasks['task4'].doLast { println "-----Access tasks by name-----" println tasks.findByName('task2') println tasks.getByName('task2') println tasks.findByName('task0') // println tasks.getByPath('task0') }
// TaskCollection.java // TaskContainer inherits from taskcollection < task > and polymorphicdomainobjectcontainer < task > // The getByName method comes from TaskCollection @Override T getByName(String name) throws UnknownTaskException; // NamedDomainObjectCollection.java // TaskCollection inherits NamedDomainObjectSet // NamedDomainObjectSet inherits NamedDomainObjectCollection // The findByName method comes from the NamedDomainObjectCollection @Nullable T findByName(String name);
5. It should be noted that when accessing a task through a path, the parameter value can be either the path or the task name, but when accessing a task through a name, the parameter value can only be the task name
3, Task grouping and description
- Task grouping is to classify tasks, which is convenient for us to classify and sort out tasks
- Task description is a description of the task to facilitate others to understand the purpose of the task
task task5 task5.group = BasePlugin.BUILD_GROUP task5.description = "This is a build Grouped tasks" task5.doLast { println "group:$group,description:$description" }
- Use the gradle tasks command to view task information, including task grouping and description
- In AS, task grouping can be seen in the Gradle Task list, and its description can be seen by hovering over a task
4, Task execution analysis
- The execution of a task is actually the execution of a series of actions in the task
// AbstractTask.java @Override public List<ContextAwareTaskAction> getTaskActions() { if (actions == null) { actions = new ArrayList<ContextAwareTaskAction>(3); } return actions; }
- See the execution of the task through the source code (version number: 7.0.2)
- Examples
task executeTask(type: Task6) executeTask.doFirst { println "Task Execute before self execution doFirst" } executeTask.doLast { println "Task Execute after self execution doLast" } class Task6 extends DefaultTask { @TaskAction def doSelf(){ println "Task Self execution doSelf" } }
- doSelf() method of source code analysis - when creating a task, Gradle will parse the method marked with @ TaskAction annotation in the task as the Action executed by the task, and then use prependParallelSafeAction(...) Method to add the Action to the execution list of the Action
// AbstractTask.java @Override public void prependParallelSafeAction(final Action<? super Task> action) { if (action == null) { throw new InvalidUserDataException("Action must not be null!"); } getTaskActions().add(0, wrap(action)); }
- doFirst(...) method of source code analysis - always insert at the first place in the Action execution list, focusing on gettaskactions() add(0, wrap(Action, actionName));
// AbstractTask.java @Override public Task doFirst(final Action<? super Task> action) { return doFirst("doFirst {} action", action); } @Override public Task doFirst(final String actionName, final Action<? super Task> action) { hasCustomActions = true; if (action == null) { throw new InvalidUserDataException("Action must not be null!"); } taskMutator.mutate("Task.doFirst(Action)", new Runnable() { @Override public void run() { getTaskActions().add(0, wrap(action, actionName)); } }); return this; }
- doLast(...) method of source code analysis - always insert at the end of the Action execution list, focusing on gettaskactions() add(wrap(Action, actionName));
// AbstractTask.java @Override public Task doLast(final Action<? super Task> action) { return doLast("doLast {} action", action); } @Override public Task doLast(final String actionName, final Action<? super Task> action) { hasCustomActions = true; if (action == null) { throw new InvalidUserDataException("Action must not be null!"); } taskMutator.mutate("Task.doLast(Action)", new Runnable() { @Override public void run() { getTaskActions().add(wrap(action, actionName)); } }); return this; }
5, Task sorting
It's not accurate to say sorting. It should be said that task A is specified to execute after task B is executed, and whether it is executed or not may be different according to the api called
- Shouldranafter should be executed after
- mustRunAfter must be executed after
task taskA taskA.doLast{ println "TaskA implement..." } task taskB taskB.doLast{ println "TaskB implement..." } taskA.mustRunAfter taskB
6, Enabling and disabling tasks
Enabled attribute. The default value is true, which means that the task is enabled. If it is set to false, the task will be disabled
task task7 task7.doLast{ println "Task7 implement..." } task7.enabled = false
7, onlyIf assertion for task
- What is an onlyIf assertion: it is a conditional expression. There is an onlyIf method in the Task class. This method receives a closure parameter and determines whether to execute or skip the Task according to the return value of true/false
- Example:
task task8 task8.onlyIf{ println "Task8 implement..." false } task task9 task9.onlyIf{ println "Task9 implement..." true }
8, Task rules
- adopt Section II We know a variety of ways to access tasks. When we access tasks by task name, if the corresponding task does not exist, we will call the rules we added to deal with this situation
// DefaultNamedDomainObjectCollection.java @Override public T findByName(String name) { T value = findByNameWithoutRules(name); if (value != null) { return value; } ProviderInternal<? extends T> provider = index.getPending(name); if (provider != null) { // TODO - this isn't correct, assumes that a side effect is to add the element provider.getOrNull(); // Use the index here so we can apply any filters to the realized element return index.get(name); } if (!applyRules(name)) { return null; } return findByNameWithoutRules(name); }
- Example:
tasks.addRule "This is the description of the task rule",{ String taskName -> task(taskName).doLast{ println "$taskName Does not exist and cannot be executed..." } }
- If no rule is added, the task not found will fail to compile
- The task not found after adding the rule will be executed according to the rule (for example, print information)
Organize and study the Android Gradle authoritative guide and Internet materials from the ruthless boss of Feixue