Gradle executes the procedure
1. Initialization phase 2. Configuration phase 3
The initialization phase actually corresponds to our settings.gradle file. The configuration phase is basically to build up the dependencies between our tasks and our tasks which is a directed acyclic graph of who executes first and who executes last. The execution phase is when Gradle finally builds your project
Task definition and configuration
The most important attribute in the definition of a task is the group attribute. Many people ignore this attribute, resulting in the definition of all tasks in the default Other group, which is difficult to find.
You can also look at the total number of tasks that can be set
Note the timing of the execution of the task code, for example
Task helloTask {println 'helloTask1 'doFirst {println("helloTask2")}} task helloTask {println 'helloTask1' doFirst {println("helloTask2")}Copy the code
Let’s look at the results
That is, the statements you write directly in the task are executed in the config phase. Only things written in doFirst or Dolast packages are executed in gradle execution
Statistics the duration of assembleDefaultDebug
With that in mind, let’s do a simple feature that counts the time it takes to build a task. To count its elapsed time we must know where the assembleDefaultDebug task started. We can just type the build command and see which task to start from
You can see from the figure above that this starts with the preBuild task.
this.afterEvaluate { Project project ->
def preTask = project.tasks.getByName('preBuild')
def t1
preTask.doFirst {
t1 = System.currentTimeMillis()
}
def buildTask = project.tasks.getByName('assembleDefaultDebug')
buildTask.doLast {
println("build takes:" + (System.currentTimeMillis() - t1))
}
}
Copy the code
Let’s look at the results
Task dependent on
I’m not going to repeat some of the dependencies that you can find all over the Internet, but I’m going to talk about some that others haven’t.
First, a task can depend on multiple tasks. It does not mean that a task can only depend on one task
task taskX{
doLast {
println "taskX"
}
}
task taskY{
doLast {
println "taskY"
}
}
task taskZ(dependsOn:[taskX,"assembleDebug"]){
doLast {
println "taskZ"
}
}
Copy the code
In addition, taskZ relies on Task X and Task Y in the above example, so don’t assume that just because I wrote Task X before taskY that X was executed before Y. There are a lot of people on the Internet who say that taskX and taskY are executed in random order, but from my own testing results, it seems that this is not the case. Instead, taskX and taskY are based on the names of the taskX and taskY, starting with the first letter and executing the larger letters first. Maybe it’s because my Gradle version is too high? Anyway, you should be careful here, do more tests, and communicate with me on the message board
In addition, tasks can be dynamically dependent. For example, you can rely on tasks that conform to certain rules.
DependsOn this.tasks.findall {task -> return task.name. StartsWith ("build")} doLast {dependsOn this.tasks.findall {task -> return task.name. println "taskZ" } }Copy the code
Task INPUT output
Let’s first look at the output of the program
You can see that only output from files or file paths is supported.
In addition to file and file path input, map type input is also supported. Note that the map value is object, which means that any type can be supported.
To make a small function, we output our Android minSdk and versionSdk and so on into a file.
ext { mMinSdkVersion = 26 mTargetSdkVersion = 29 infoFile = file(this.projectDir.toString() + "/info.txt") if (! infoFile.exists()) { infoFile.createNewFile() } }Copy the code
Define version and then the output file.
Look at the write file task
task writeInfoTask() {
inputs.property("mMinSdkVersion", this.mMinSdkVersion.toString())
inputs.property("mTargetSdkVersion", this.mTargetSdkVersion.toString())
outputs.files this.infoFile
doLast {
println("writeInfoTask")
def data = inputs.getProperties()
File file = outputs.getFiles().getSingleFile()
file.write(data.toString())
}
}
task zreadInfoTask() {
inputs.files this.infoFile
doLast {
println("readInfoTask")
File file = inputs.getFiles().getSingleFile()
println("file content:" + file.text)
}
}
Copy the code
Finally, let’s perform this task
task taskX {
dependsOn(writeInfoTask, zreadInfoTask)
doLast {
println("task all over")
}
}
Copy the code
Notice why I’m calling it zredInfoTask instead of readInfoTask? Gradle can decide intelligently if the input of a task depends on the output of another task. Gradle can intelligently put the output of the task in front of the input file and the input task in back. But according to my tests here, that’s not the case. Try it out for yourself and see if the gradle version causes this feature to be different.
There is also a mustRunAfter function that guarantees execution after a task has finished. Those interested can explore on their own.