前言:
大家回想一下自己第一次接觸Gradle
是什么時候?
相信大家也都是和我一樣,在我們打開第一個AS項目的時候,
發現有很多帶gradle字樣的文件:setting.gradle, build.gradle,gradle.warpper
,以及在gradle
文件中各種配置,
這些都是啥wy啊。。
特別對于一些小公司開發人員,因為接觸架構層面的機會很少,可能在使用AS幾年后都不一定對Gradle
有太多深入了解,這是實話,因為筆者就是這么過來的。。
而Gradle
又是進階高級
開發的必經之路。
好了,接下來進入正題,此系列筆者會由淺入深的方式,帶領大家來了解下,Gradle
背后究竟有哪些奧秘。
1.Gradle
定義:
很多開發喜歡把Gradle
簡單定義為一種構建工具,和ant,maven
等作用類似,
誠然Gradle確實是用來做構建,但是如果簡單得把Gradle拿來做構建,就太小看Gradle了.
筆者更愿意將Gradle看做一種編程框架
。在這個框架中,你可以做很多ant,maven等常用構建工具做不了的事情,
如將自己的任務task集成到構建生命周期中,完成文件拷貝,腳本編寫等操作。
2.Gradle
優缺點:
相較早期的構建工具:ant,maven等。
優點如下:
-
1.使用DSL Grovvy語言來編寫: :了解ant的同學應該都知道:ant使用的是xml配置的模式,而Gradle使用的是
表達性的Groovy
來編寫,Groovy同時
支持面向對象和面向過程
進行開發,這個特性讓Groovy
可以寫出一些腳本的任務,這在傳統ant,maven上是不可能實現的 -
2.基于java虛擬機: :
Groovy
是基于jvm
的語言,groovy
文件編譯后其實就是class文件,和我們的java
一樣。
所以在gradle構建過程中,我們完全可以使用java/kotlin去編寫我們的構建任務以及腳本,極大的降低我們學習的成本。
- 3.Gradle自定義task :可以構建自己的任務,然后掛接到gradle構建
生命周期
中去,這在ant,maven上也是不可能實現的, - 4.擴展性好 :gradle將關鍵配置扔給我們開發者,開發者配置好任務后,無需關心gradle是如何構建的。
- 5.支持增量更新 :增量更新可以大大加快我們的編譯速度
關于Groovy的語法篇:可以參考這篇文章:
Gradle筑基篇(二)-groovy語法詳解
缺點:
用過gradle都知道,低版本gradle的項目在高版本的gradle中經常出現很多莫名其妙的錯誤,向后兼容性較差。
3.Gradle
工程結構:
gradle標準工程代碼如下
├── moduleA
│ └── build.gradle
├── moduleB
│ └── build.gradle
├── build.gradle
├── settings.gradle
├── gradle.properties
├── local.properties
├── gradle
│ └── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
└── gradlew.bat
- 1.
build.gradle
:可以理解為一個Project腳本,Project腳本中有自己的任務,最外層的Project為rootProject - 2.
settings.gradle
:主要用來配置我們項目中需要用到的模塊。用include關鍵字給包裹進 - 3.
gradle.properties
:這個文件主要是設置一些全局變量,包括jvm運行以及自定義的一些全局參數 - 4.
local.properties
:這個文件主要配置一些本地的sdk和ndk版本信息以及路徑 - 5.
gradle-wrapper.jar
:負責自動下載Gradle腳本運行環境 - 6.
gradle-wrapper.properties
:用來配置當前使用的Gradle的版本以及存儲的路徑
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\\://services.gradle.org/distributions/gradle-6.5-bin.zip
distributionBase + distributionPath:指定Gradle安裝路徑;
zipStoreBase + zipStorePath:指定Gradle安裝包的存儲路徑;
distributionUrl:Gradle版本的下載地址。
注意這里如果將bin改為all,則可以查看當前Gradle的源碼信息。
- 7.
gradlew和gradlew.bat
:用來執行構建任務的腳本,可以在命令行使用gradlew xxxTask
4.Gradle生命周期
Gradle作為新興的構建工具,其內部也有自己的生命周期階段,每個階段做的事情都層次分明,
了解Gradle生命周期,才能很好的使用我們的Gradle工具。
1.初始化階段
做了哪些事情?:
- 1.初始化
Setting.gradle
文件,獲取setting
實例, - 2.執行
setting
中的腳本,根據include
字段,創建對應的project
實例 - 3.設置構建需要的環境
注意:初始化階段執行任何任務都會執行一次。
Project實例關系如下:
gradleproject樹.png
2.配置階段
- 1.下載所有插件和構建腳本依賴項
- 2.執行
build.gradle
文件中的腳本信息 - 3.實現task任務的拓撲圖,這個圖是一個
有向無環圖
,防止任務執行進入死循環。
注意:配置階段執行任何任務都會執行一次。
3.執行階段
執行階段就是根據當前task拓撲圖進行執行task任務。
需要注意以下幾點:
-
1.在項目中配置的
doLast,doFirst
操作,都會在任務執行階段執行,而不會在配置階段執行,而如果任務需要執行,需要掛接到
gradle執行生命周期
中,筆者開始接觸gradle時就踩過這個坑。。這塊后面講解task
的時候在來具體講解 -
2.前面也說了初始化階段和配置階段在每個任務執行前都會執行,所以 不要在前兩個階段進行一些耗時的操作 ,這樣可能每次編譯執行你都會崩潰的
5.Gradle生命周期監聽:
要查找Gradle是如何監聽生命周期,可以到Gradle
源碼中看看:
-
1.監聽初始化階段
初始化階段主要用來初始化
Setting.gradle
文件,獲取setting
實例,創建Project
實例等,所以其可用下面代碼監聽:
//開始初始化Setting.gradle前
this.gradle.beforeSettings {
println "beforeSettings"
}
//Setting.gradle配置完畢后,創建了setting實例
this.gradle.settingsEvaluated {
println "settingsEvaluated"
}
//執行解析Setting.gradle文件后,創建了project實例列表
this.gradle.projectsLoaded {
println "projectsLoaded"
}
- 2.監聽配置階段
2.1:監聽當前project的配置階段前后:
在Project源碼
中可以看到:
/**
* Adds an action to execute immediately before this project is evaluated.
*
* @param action the action to execute.
*/
void beforeEvaluate(Action? action);
/**
* Adds an action to execute immediately after this project is evaluated.
*
* @param action the action to execute.
*/
void afterEvaluate(Action? action);
/**
* Adds a closure to be called immediately before this project is evaluated. The project is passed to the closure
* as a parameter.
*
* @param closure The closure to call.
*/
void beforeEvaluate(Closure closure);
/**
* Adds a closure to be called immediately after this project has been evaluated. The project is passed to the
* closure as a parameter. Such a listener gets notified when the build file belonging to this project has been
* executed. A parent project may for example add such a listener to its child project. Such a listener can further
* configure those child projects based on the state of the child projects after their build files have been
* run.
*
* @param closure The closure to call.
*/
void afterEvaluate(Closure closure);
看這兩個方法的說明就是用來監聽配置階段,傳入的是一個Action或者傳入一個閉包,閉包的代理為當前Project
使用方式如下 :
//監聽project被配置前
this.beforeEvaluate {Project project ->
println "${project.name} :beforeEvaluate"
}
//監聽project被配置后
this.afterEvaluate {Project project ->
println "${project.name}:afterEvaluate"
}
注意:這個監聽只是針對當前Project的配置階段而不是所有Project的配置
你也可以使用:
this.project.beforeEvaluate
this.project.afterEvaluate
那么有沒有可以監聽所有Project的配置階段的api呢?安排
2.2:監聽每個Project的配置前后:
使用this.gradle的內部方法,因為gradle是相對于整個工程作為作用域
//監聽所有的Project的被配置前
this.gradle.beforeProject {Project project ->
println "${project.name}:beforeProject"
}
//監聽所有的Project的被配置后
this.gradle.afterProject {Project project ->
println "${project.name}:afterProject"
}
編譯下看看:
> Configure project :
gradle_source_plugin:afterProject
> Configure project :app
app:beforeProject
do app evaluating
app:afterProject
> Configure project :application
application:beforeProject
do application evaluating
application:afterProject
看到當前工程所有的project都調用了一次beforeProject和afterProject
那有同學又要問了,有沒有監聽整個project配置階段的:當然有
2.3:監聽全部project配置階段的前后
this.gradle.projectsEvaluated {
println "all projectsEvaluated"
}
這個閉包可以監聽整個項目的配置完畢后的事件
配置階段還有一些監聽如下:
2.4:監聽任務的添加操作
this.project.tasks.whenTaskAdded {Task task->
println "${task.name}:whenTaskAdded"
}
2.5:監聽任務拓撲圖的執行
//task拓撲圖構造完畢
this.gradle.taskGraph.whenReady {TaskExecutionGraph graph->
println "taskGraph:->"+graph
}
監聽拓撲圖完畢后其實才是真正的配置階段完畢 ,瞧瞧源碼:
在BasePlugin中:
threadRecorder.record(
ExecutionType.BASE_PLUGIN_PROJECT_CONFIGURE,
project.getPath(),
null,
this::configureProject);
threadRecorder.record(
ExecutionType.BASE_PLUGIN_PROJECT_BASE_EXTENSION_CREATION,
project.getPath(),
null,
this::configureExtension);
threadRecorder.record(
ExecutionType.BASE_PLUGIN_PROJECT_TASKS_CREATION,
project.getPath(),
null,
this::createTasks);
看到配置階段最后一步才是創建Task,所以可以使用this.gradle.taskGraph.whenReady監聽整個配置階段的結束
- 3.監聽執行階段
3.1:監聽任務執行:
gradle.taskGraph.beforeTask { Task task ->
println "${task.name}:beforeTask"
}
gradle.taskGraph.afterTask {Task task ->
println "${task.name}:afterTask"
}
執行下面任務:
task clean(type: Delete) {
doFirst {
println 'clean:doFirst'
}
doLast {
println 'clean:doLast'
}
delete rootProject.buildDir
}
結果:
> Task :clean
clean:beforeTask
clean:doFirst
clean:doLast
clean:afterTask
可以看到在task執行前后調用了監聽中的方法
3.2:監聽執行任務階段開始
其實可以使用配置階段的this.gradle.taskGraph.whenReady,這個就是所有project配置完畢,且生成了task拓撲圖
下一步就是開始執行任務了
3.3:監聽執行任務階段結束
this.gradle.buildFinished {}
這個可以監聽所有任務執行完畢后事件回調:
-
DSL
+關注
關注
2文章
58瀏覽量
38273 -
AS
+關注
關注
0文章
27瀏覽量
26066 -
gradle
+關注
關注
0文章
26瀏覽量
703
發布評論請先 登錄
相關推薦
評論