preface
In previous installments, I’ve covered the basic syntax of Groovy. Learning new syntax is always a tedious process, but it’s one you must go through in order to master Gradle. Of course, this chapter will start from the ground up and explain Gradle.
1. Master Gradle basics
1.1 Environment Configuration
- Go to the official website to download gradle or from the.gradle/wrapper/dists directory.
- System property configuration:
- Add GRADLE_HOME: C:\Users\sheji.gradle\wrapper\dists\gradle-6.5-all\gradle-6.5
- Add Path: %GRADLE_HOME%\bin
- Check the configuration
Enter gradle -v in the CMD command window to see if the current gradle version is displayed
1.2 Hello Gradle!
The first program we learn in any development language is the Hello program. So there’s still a sense of ritual.
- In the project folder, create a build.gradle file:
- Write code in a file
task hello{ println 'Hello, Gradle! ' } Copy the code
- Open CMD, go to the project directory, and run the > gradle -q hello command
- The final result
As is shown in
When it runs successfully, the. Gradle folder is automatically created.
At this point we continue to execute the command gradle Wrapper in the command window
As is shown in
In this directory, the system automatically helped us to create a series of files and folders, these files are familiar, open AS and IDEA comparison, found that there are corresponding compilers in the directory.
This is a standard Gradle project directory structure:
Gradlew and gradlew. Bat are executable scripts for Linux and Windows respectively. The business logic is implemented in /gradle/wrapper/gradle-wrapper.jar. Gradlew ultimately uses Java to execute the jar to perform the Gradle operations.
1.2.1 gradle – wrapper. The properties
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\:/ / services.gradle.org/distributions/gradle-6.1.1-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
Copy the code
This code is the contents of this file and will now be interpreted one by one
- DistributionBase: The home directory where the downloaded Gradle compressed package is stored after it is decompressed
- DistributionPath: The path to the decompressed Gradle archive relative to distributionBase
- DistributionUrl: The download address of the Gradle distribution zip
- -bin: binary release
- -all: bin Contains source code and documents
- ZipStoreBase: Same as the distributionBase, except that it stores the zip package
- ZipStorePath: Same as the distributionPath, except that it stores the zip package
The value of distributionBase is GRADLE_USER_HOME
1.2.2 GradleUserHome Property Interpretation
- The default path is ~/. Gradle /. It is not recommended to use local Maven m2 instead, because the modules in the original. Gradle directory are very clear
- If you specify a different directory instead of GradleUserHome at startup, you will need to re-download the plugin and rely on the new directory each time you build
- By default, when Gradle runs, in addition to dealing with projects, there is also a new GradleUserHome directory built by the current project. All jar packages have to be re-downloaded
1.3 Gradle Part command line
- gradlew -? /-h/-help Uses help
- Gradlew Tasks Displays all executable tasks
- Gradlew –refresh-dependencies assemble forces the refresh dependency
- Gradlew cBC is equivalent to executing Task cleanBuildCache, which executes tasks quickly with an abbreviated name
- Gradlew :app:dependencies Finds the app project dependency tree
2. Familiar with Gradle build mechanism
2.1 Be familiar with the functions of setting.gradle
We continue to look at the Java, Android project directory
As is shown in
Setting. gradle = setting.gradle = setting.gradle = setting.gradle = setting.gradle = setting.gradle = setting.gradle = setting.gradle = setting.gradle = setting.gradle = setting.gradle = setting.gradle = setting.gradle
- Gradle supports building multiple projects. Use settings. Gradle to configure adding sub-projects (modules).
- The Settings file is executed during initialization, creating a Settings object and calling its methods when the script is executed
- Settings.include(String… projectPaths)
- Add the given directory to the project build, with ‘:app’ representing the relative path of the file, equivalent to the ‘./app’ folder
- Multi-project architecture is layered, and sub-projects at the same level are placed in the same folder for easy management, which is represented by ‘: XXX: YYy ‘
As I just said, the Settings file executes during the initialization phase, so what are the other phases? This starts with the Gradle life cycle.
2.2 Be familiar with the Gradle lifecycle
The Gradle lifecycle consists of three things: Initialization, Configuration, and Execution
- Initialization
- Gradle supports both single and multi-project builds. During the initialization phase, Gradle determines which projects will participate in the build and creates a Project instance for each Project, which is not normally touched. (such as resolving settings.gradle)
- Configuration
- In the configuration phase, the build.gradle file of each project is parsed, the subset of tasks to be executed is created, the relationships between tasks are determined, and some initial configurations are made for the tasks.
- Execution
- In the run phase, Gradle executes tasks based on the subset of tasks created and configured for execution in the configuration phase.
These three life cycles are closely related to the execution process.
2.3 Be familiar with Gradle execution process
As is shown in
It can be seen from this figure that different stages have corresponding method call sequence, and we can get familiar with these temporarily here:
- Setting.gradle in the initialization phase
- All of the configuration phase
- All of the execution phases
Now that you’ve explained what setting.gradle does, let’s move on to the configuration phase.
2.4 Be familiar with Gradle configuration
- Build. Gradle for each Project is parsed. gradle tasks for each Project are not executed.
- After the ration stage, the relationships between projects and internal tasks are determined. A Project contains many tasks, each of which has dependencies. Configuration creates a directed graph describing the dependencies between tasks. After all projects are configured, there is a callback project.afterevaluate () indicating that all modules have been configured.
Gradle tasks (Task lists) and Gradle tasks (Task lists) are linked to Gradle tasks (Task lists).
2.5 Be familiar with Gradle tasks
Gradle Task:
- Task is the smallest task unit in Gardle, and complex operations can be performed between tasks (such as dynamic task creation, inter-task dependency calls, etc.). Gradle execution is a combination of tasks that build projects
- Using the gradlew help command, which is available to any Gradle project, you can execute this command to see if taks is executing the process as expected
- You can view the runnable tasks using the tools or using the gradlew Tasks command.
- Use the gradlew tasks –all command to view all tasks
- Use the gradlew A B command to execute tasks A and B. Hump shorthand is supported
Note: Task is the smallest task unit in Gardle, just like the unit of money we commonly use today.
The concept has said a lot of, the next to the happy masturbation code verification link.
To create a Gradle project in Java, go to Build. Gradle
this.beforeEvaluate {
println "this.beforeEvaluate"
}
BeforeEvaluate / / equivalent
this.gradle.beforeProject {
println "this.beforeProject"
}
this.afterEvaluate {
println "this.afterEvaluate"
}
// After the equivalent configuration phase is complete
this.gradle.afterProject {
println "this.afterProject"
}
this.gradle.taskGraph.whenReady{
println "whenReady"
}
// Gradle3.0 << is deprecated above 4.x
task A {
println "configuration A.."
doFirst {
println "doFirst A.."
}
doLast {
println actions
println "doLast A1.."
}
}
task B{
println "configuration B.."
doFirst {
println "doFirst B.."
}
doLast {
println actions
println "doLast B1.."}}this.gradle.buildFinished {
println "buildFinish"
}
Copy the code
Code parsing
The first several “this” points to the corresponding method, which is the corresponding method of the flow chart. After that, we define two task units, which have different printouts for different actions.
Result 1: Run taskA
As is shown in
Click the Task in the task list on the right or click the run button for the corresponding task on the left
> Configure project :
configuration A..
configuration B..
this.afterProject
this.afterEvaluate
whenReady
> Task :A
doFirst A..
[org.gradle.api.internal.AbstractTask$ClosureTaskAction@261ae6e0, org.gradle.api.internal.AbstractTask$ClosureTaskAction@76e733fb]
doLast A1..
buildFinish
Copy the code
We found that during the configuration phase, the configuration in both tasks was printed, followed by the completion of the configuration and whenReady methods ready for execution. In the taskA execution phase, doFirst is run first, doLast action is run second, and buildFinish is called to finish Gradle compilation as desired.
However, there is a small flaw: the beforeEvaluate, beforeProject corresponding method before configuration is not printed, if there is a big boss who knows the reason is welcome to communicate with each other. This does not affect our performance, however, as the configuration code for each task is executed at build time.
We found that when running A or B alone, the configuration stage performed the configuration of the corresponding task, but the operation did not run together. When we use Android Gradle, we always run the whole operation, just like the configuration stage. So how do we do that?
task A {
println "configuration A.."
doLast {
println actions
println "doLast A1.."
}
}
task B{
println "configuration B.."
doLast {
println actions
println "doLast B1.."
}
}
A.dependsOn B
Copy the code
A inherits B from A; run A from B;
> Configure project :
configuration A..
configuration B..
> Task :B
[org.gradle.api.internal.AbstractTask$ClosureTaskAction@213f5745]
doLast B1..
> Task :A
[org.gradle.api.internal.AbstractTask$ClosureTaskAction@70cabab9]
doLast A1..
Copy the code
We found that when I run A, they both run together, but the problem is that when I run B, they run separately, and what if there are multiple tasks? We can’t dependsOn each other, can we?
Next came a series of modifications to the code:
task A {
println "configuration A.."
doLast {
println actions
println "doLast A1.."
}
}
task B{
println "configuration B.."
doLast {
println actions
println "doLast B1.."
}
}
task C {
println "configuration C.."
doLast {
println "doLast C.."
}
}
task hello2(dependsOn: [A, C, B]) {
doLast {
println "doLast hello2"}}Copy the code
Here we can see that the new task hello is defined, and then the existing tasks are bound to each other in the form of an array. In other words, we define a management class that manages all the scattered task units. To run all the task units, we only need to run this management class. So try running the Hello2 task unit:
> Configure project :
configuration A..
configuration B..
configuration C..
> Task :A
[org.gradle.api.internal.AbstractTask$ClosureTaskAction@40880123]
doLast A1..
> Task :B
[org.gradle.api.internal.AbstractTask$ClosureTaskAction@111c4be4]
doLast B1..
> Task :C
doLast C..
> Task :hello2
doLast hello2
BUILD SUCCESSFUL in 0s
4 actionable tasks: 4 executed
18:33:17: Task execution finished 'hello2'.
Copy the code
In the code, I’m going to convert B and C to each other, and it turns out that when you run units, you run them alphabetically.
Now there is a new problem. When we use any object, it will be recycled after it is used, so will there be a corresponding reclamation task after the task is executed? What keywords should you use?
Continue to modify the code:
task A {
println "configuration A.."
doLast {
println actions
println "doLast A1.."
}
}
task B{
println "configuration B.."
doLast {
println actions
println "doLast B1.."
}
}
task C {
println "configuration C.."
doLast {
println "doLast C.."
}
}
task hello2(dependsOn: [A, C, B]) {
doLast {
println "doLast hello2"
}
}
task finalized {
doLast {
println "clear all tasks"
}
}
hello2.finalizedBy finalized
Copy the code
The finalizedBy keyword is used to associate the total management task with the cleanup task. The finalizedBy keyword is used to associate the total management task with the cleanup task
> Configure project :
configuration A..
configuration B..
configuration C..
> Task :A
[org.gradle.api.internal.AbstractTask$ClosureTaskAction@25b5129e]
doLast A1..
> Task :B
[org.gradle.api.internal.AbstractTask$ClosureTaskAction@74447d23]
doLast B1..
> Task :C
doLast C..
> Task :hello2
doLast hello2
> Task :finalized
clear all tasks
Copy the code
At this point, we should have a general idea of Gradle tasks. Each task is the smallest unit and each task has its own actions. A Gradle build is the result of each task unit executing on each other.
conclusion
This is the end of this article. I believe you have some idea of Gradle’s basics and build mechanism. In the next article, you will continue to explain Gradle further.