The default tool for Android Studio is Gradle. Developers usually do not need to know Gradle script configuration to develop an App, but if you need to modify the output directory in the package to speed up the package, you need to have a deep understanding of Gradle. Gradle can not only be used as a tool to learn Gradle, but also as a programming framework. Here is the Gradle API document, and then we write and compile scripts. In fact, we are playing Gradle API.
Gradle consists of three parts:
- Groovy core syntax
- Build script block
- Gradle API: Contains project, Task/Settiing, and more, which will be highlighted next.
Gradle advantage
- In terms of flexibility, Gradle supports scripting based on the Groovy language and focuses on the flexibility of the build process. It is suitable for building projects with high complexity and can accomplish very complex builds.
- In terms of granularity, Gradle builds granular to each task. And all of its Task source is open source, after we master the whole packaging process, we can modify its Task to dynamically change its execution process.
- Gradle supports a plug-in mechanism for extensibility, so we can reuse plug-ins as easily as we reuse libraries.
Grale builds the life cycle
Running./gradlew build is one of the most complex task commands. (./gradlew is the syntax in MAC)
As you can see, each time the task takes a long time, because the build task depends on many tasks, and it will execute its own task after completing the task it depends on. Let’s take a look at the Gradle build process first.
The Gradle build process can be divided into three parts: the initialization phase, the configuration phase, and the execution phase.
Initialization phase
Gradle creates a Project instance for each Project. In a multi-project build, Gradle finds out which Project dependencies need to participate in the build. The script associated with initialization is settings.gradle, which reads out how many projects there are in the entire project.
The configuration phase
The tasks of the configuration phase are to execute the build.gradle script under each section, complete the Project configuration, and construct the Task dependency diagram to execute tasks according to the dependencies during the execution phase.
Gradle has a Project object for each build.gradle, and the code executed in the configuration phase includes statements in build.gralde, closures, and configuration section statements in Task.
Execution phase
At the end of the configuration phase, Gradle creates a directed acyclic graph based on the dependencies of the tasks. This can also be accessed through the getTaskGraph method of Gradle objects. The corresponding class is TaskExecutionGraph, which is then executed by calling Gradle < Task >.
Gradle lifecycle listens
Add lifecycle listeners to Project
Now let’s look at some of the most common listening methods in development:
// called before Project is configured
void beforeEvaluate(Closure closure)
// called after the Project configuration is complete
void afterEvaluate(Closure closure)
Copy the code
Here’s an example to verify the result:
setting.gradle
include ':app'
println 'Initialization phase begins... '
Copy the code
Build. gradle in the root directory
// Configure the submodule
subprojects { sub ->
sub.beforeEvaluate { proj ->
println "Subitem beforeEvaluate callback..."
}
}
println "Root project configuration begins --"
task rootTest {
println "Task Configuration in root project --"
doLast {
println "Execute root project task..."
}
}
println "End of root project configuration --"
Copy the code
Build. gradle in app directory
println "APP subproject configuration starts --"
afterEvaluate {
println APP subproject afterEvaluate callback...
}
task appTest {
println "Task configuration in APP subproject --"
doLast {
println "Perform sub-project tasks..."
}
}
println "End of APP subproject configuration --"
Copy the code
Run ‘./gradlew clean ‘to get the following output:
Initialization phase begins... Root project configuration start -- Task configuration in root project -- Root project configuration end -- subproject beforeEvaluate callback... APP subproject configuration start -- APP subproject task configuration -- APP subproject configuration end -- APP subproject afterEvaluate callback...Copy the code
Add a lifecycle listener to Gradle
In setting.gradle add:
include ':app'
gradle.addBuildListener(new BuildListener() {
// called before the build starts
void buildStarted(Gradle var1) {
println 'Construction begins... '
}
// Settings. gradle is called after settings.gradle is configured
void settingsEvaluated(Settings var1) {
// var1.gradle.rootProject
// Because the initialization of Project has not been completed.
println 'Settings: Perform settingsEvaluated... '
}
// Called when all projects introduced in settings.gradle have been created. Settings only take effect in that file
void projectsLoaded(Gradle var1) {
println 'Settings: Execute projectsLoaded... '
println 'Initialization completed, root project accessible:' + var1.gradle.rootProject
}
// called after all project configurations are complete
void projectsEvaluated(Gradle var1) {
println 'Settings: executive projectsEvaluated... '
}
// Child Project must be set in root project to take effect. Root project must be set in settings.gradle to take effect
void beforeProject { proj ->
println "Settings: Execute ${proj.name} beforeProject"
}
// called after project is configured
void afterProject { proj ->
println "Settings: Execute ${proj.name} afterProject"
}
// called after the build is finished
void buildFinished(BuildResult var1) {
println 'Build complete'}})Copy the code
Take a look at the output:
Settings: Perform settingsEvaluated... Settings: Execute projectsLoaded... Settings: Run GradleTestDemo beforeProject Root project Configuration starts -- Task configuration in the root project -- Root project configuration ends -- Settings: Execute GradleTestDemo afterProject Settings: Execute app beforeProject subproject beforeEvaluate callback... APP subproject configuration start -- APP subproject task configuration -- APP subproject configuration end -- APP afterProject afterEvaluate callbacksettings:Perform projectsEvaluated... End of build...Copy the code
There are other listening methods:
this.gradle.beforeProject{} // Equal to beforeEvaluate
this.graddle.afterProject{} // Equivalent to afterEvaluate
// All of the following can be monitored
this.gradle.addListener
tthis.gradle.addProjectEvaluationListener
Copy the code
After learning about gradle’s life cycle listening, I wonder why other commands output when executing build commands. Here’s a picture:
This graph will be completed during the configuration phase, forming a directed acyclic graph. When executing a task named build, other dependent tasks will be completed.
TaskExecutionGraph
After being configured, Gradle generates directed acyclic graphs of all tasks. These are called task execution graphs. They determine the order in which tasks are executed, etc.
The TaskExecutionGraph API documentation shows the common API methods:
API | describe |
---|---|
addTaskExecutionGraphListener | Add a listener to the task execution diagram |
addTaskExecutionListener | Add a listener to the task execution |
whenReady | Called when the task execution diagram is filled |
beforeTask | When a task is called before it executes |
afterTask | This command is called when a task is completed |
hasTask | Query whether the task exists |
getAllTasks | Get all tasks |
Set getDependencies(Task task) | Returns the dependency of the parameter Task |
Gradle also listens for the execution life cycle of a task.
TaskExecutionGraph taskGraph = gradle.getTaskGraph()
taskGraph.whenReady {
println "task whenReady"
}
taskGraph.beforeTask { Task task ->
println "Task name: ${task.name} beforeTask"
}
taskGraph.afterTask { Task task ->
println ${task.name} afterTask
}
Copy the code
reference
In-depth understanding of Android Gradle
Explore Gradle automation building technology
After reading this series, you will understand Gradle completely
Gradle Foundation – Build lifecycle and Hook technology
Gradle build life cycle