Gradle core: Task and actual combat

Knowledge graph

Insert picture description here

1. Task definition configuration

1. Common creation methods
  • task method of project
  • The create method of the tasks attribute of the project

(1) Task creation chestnut

// project 对象的task方法
// 参数 为task名字 、闭包体
task customTask {
    
    
    print " i am custom task"
}

// 参数参数 为task名字 、闭包体
this.tasks.create(name: "customTask1") {
    
    
    print " i am custom task 1"
}

There is almost no difference in the use of the two

(2) tasks attribute

TaskContainer getTasks();
-------------------
TaskContainer 提供的方法:
// 根据路径名,返回task对象,找不到时返回null
Task findByPath(String path); 
// 根据路径名,返回task对象,找不到时抛出异常
Task getByPath(String path) throws UnknownTaskException;
// 创建task
Task create(String name, Closure configureClosure) throws InvalidUserDataException;

1. Gradle actually manages all tasks under the project through the task container.
2. TaskContainer provides operations such as task search and addition.
3. No matter how you add tasks, gradle will form a directed acyclic graph in the task phase.

2. Common configuration methods of task
  • Configure directly when creating
  • Create configuration in code block()
//1、创建时直接配置
// group :为任务添加分组
// description:为任务添加注释(类似类的注释)
task customTask (group:"myGroup",description:"task study"){
    
    
    print " i am custom task"
}
//2、创建代码块中配置
//通过setXXX方法指定
this.tasks.create(name: "customTask1") {
    
    
    setGroup("newGroup")
    print " i am custom task 1"
}

After grouping, we can see it in the gradle window on the right. The effect picture is as follows.
If no group is added, the new task will be added to the other group

Insert picture description here

3. Other configuration of task

Insert picture description here

1. You can see that all the configurations are in these
2. The dependencies between dependsOn specified tasks
3. Overwrite rewrites the task
4. Action configures the logic to be executed for the task.
PS: First understand, and then summarize them one by one.

Second, the execution order of Task

1. Review

Insert picture description here

Earlier we have understood the definition of task. Next, let’s take a look at the review, what performs a task, and how can another task be performed too! At this time, we review the life cycle of gradle: the
life cycle is divided into three stages: initialization, configuration, and execution. The code written in build.gradle will be inConfiguration phase execution. So is there any way to perform only the tasks we want to perform?Or specify the task to be executed in the execution phase. Please see the analysis in this section. . .

2. Execute Task at specified execution stage
  • doFirst: The code in the code block in the execution phase is executed before all Tasks
  • doLast: The code in the code block of the execution phase is executed after all tasks
task mytask1(group:"myGroup1"){
    
    
   print" 分组1内的task1"
   // 闭包内调用
    doFirst {
    
    
        print" 方式1:我在配置阶段任务中先执行"
    }
    // 
   doFirst1 {
    
    
        print" xxx"
    }
}

// task 变量名 方式调用
mytask1.doFirst {
    
    
    print" 方式2:我在配置阶段任务中先执行"
}

Insert picture description here

1. It can be seen that you only need to add the doXXX method, and the code written here isExecute during Gradle execution phase,andNot in the configuration phase.
2. The doXXX called by the task variable name is executed first than the one written in the closure (the above method 2 is preferred to the method 1)
3. When multiple doXXX are executed in order (doFirst is executed first, and doFirst1 is executed)

(1) Time-consuming statistics of actual task execution phase

// 计算build时长
def startBuildTime, endBuildTime
this.afterEvaluate {
    
    
        // 保证要找的task 配置完毕
    Project project ->
        def preBuildTask = project.tasks.findByName("preBuild")
        preBuildTask.doFirst {
    
    
            startBuildTime = System.currentTimeMillis()
            print("startTime:$startBuildTime")
        }

        def buildTask = project.tasks.findByName("build")
        buildTask.doLast {
    
    
            endBuildTime = System.currentTimeMillis()
            print("执行阶段build耗费时长:${ endBuildTime - startBuildTime }")
        }
}

Points to note:
1. Event monitoring ensures that the task configuration is complete.
2. The use of doFirst and doLast.
3. The execution order of preBuild (before the build is executed, the system will preBuild)
4. The tasks involved in the execution of the build task (refer to the build folder .dot file, use related software to convert this file into a picture)

3. The execution order of tasks3 types of designationthe way

Insert picture description here

1. Add a dependency method to the task to specify the order

After specifying the dependency for the task, the task it depends on will be executed first when the task is executed

2. Specify the input and output methods for the task to specify the order

Each task has input and output (input, output) attributes.

3. Specify the order through api

(1) By specifying dependencies for Task

Statically add task dependencies:

When you define tasks, you know which tasks to add, and you add them directly.

task  taskA{
    
    
    doLast {
    
    
        print("任务A")
    }
}

task  taskB{
    
    
    doLast {
    
    
        print("任务B")
    }
}

// 添加依赖
task  taskC(dependsOn:["taskA","taskB"]){
    
    
    doLast {
    
    
        print("任务C")
    }
}



Insert picture description here

1. Specify through dependsOn as above. Multiple dependencies are specified above and use collections. In fact, you can also specify a dependency, and the value is a string.
2. The execution order of TaskA and TaskB is random.
3. The above method is the dependency specified in the declaration. You can also specify dependencies separately: taskC.dependsOn(taskA, TaskB)

Dynamically add task dependencies:

task myTask {
    
    
   dependsOn tasks.findAll {
    
    
     Task task->return task.name.startsWith("lib")
   }
    doLast {
    
    
        println("我是MyTask")
    }
}

task libA {
    
    
    doLast {
    
    
        println("我是libA")
    }

}
task libB {
    
    
    doLast {
    
    
        println("我是libB")
    }
}

task nolib {
    
    
    doLast {
    
    
        println("我是nolib")
    }
}

Depends on tasks starting with lib

(2) By specifying input and output for Task

Insert picture description here

task libA {
    
    
    inputs.file(file("./a.txt")) // 获得输入文件(libB写好的文件)
    doLast {
    
    
        def file = inputs.getFiles().getSingleFile()
        print(file.text)
    }

}
task libB {
    
    
    // 要输入的文件
    inputs.property("key", "value")
    // 写入的地址
    outputs.dir("./a.txt")
    doLast {
    
    
        def data = inputs.getProperties()
        File file = outputs.getFiles().getSingleFile()
        // todo 其他逻辑处理
    }
}

As above, the sequential relationship established by specifying two tasks through input and output: libB executes with libA first

(3) Specify -mustRunAfter through specific api

task libC {
    
    
    mustRunAfter(libB) // 任务执行与libB之后
    doLast {
    
    
        // todo
    }
}

Extension:
1. If you want to use a custom xxx.gradle file, you can use this gradle file just by referring to the current project. (Apply from: rootProject.file("xxx.gradle"))
2. apply plugin:'com.android.application' is the task of using the system application, the plugin is similar to the java jar package, the jar package contains java classes, The plugin puts some tasks. Offer to use

Fourth, the type of task

Check and understand the official documents

The end

Guess you like

Origin blog.csdn.net/qq_38350635/article/details/103000839