環(huán)境配置
- 官方地址:https://gradle.org/releases/
-
下載之后將gradle下面的bin目錄添加到系統(tǒng)的Path中(Android studio目錄一般都是在.gradle目錄下)
image.png - 測試是否配置好:gradle -v
Hello Gradle
- 新建一個(gè)build.gradle
println("Hello Gradle")
- cmd定位到新建文件目錄下
gradle help
-
查看輸出結(jié)果
image.png - build.gradle是構(gòu)建Project的核心文件,也是入口:
- 如果沒有該文件,會(huì)出現(xiàn)not found in root project 'xxxxx' 提示異常。
- 必須要有一個(gè)可以運(yùn)行的task,運(yùn)行后自動(dòng)生成.gradle文件夾下的內(nèi)容
gradle wrapper
- Gradle Wrapper用來配置開發(fā)過程中用到的Gradle構(gòu)建工具版本。避免因?yàn)镚radle不統(tǒng)一帶來的不必要的問題
- 在工程目錄下使用cmd命令生成wrapper:
gradle wrapper
- 標(biāo)準(zhǔn)的gradle工程目錄
- gradlew和gradlew.bat分別是Linux和Windows下的可執(zhí)行腳本
- 具體業(yè)務(wù)邏輯是在/gradle/wrapper/gradle-wrapper.jar中實(shí)現(xiàn)
-
gradlew最終還是使用Java執(zhí)行這個(gè)jar包來執(zhí)行相關(guān)的Gradle操作
image.png
gradle-wrapper.properties

- distributionBase:下載的Gradle壓縮包解壓后存儲(chǔ)的主目錄
- distributionPath:相對于distributionBase的解壓后的Gradle壓縮包的路徑
- distributionUrl:Gradle發(fā)行版壓縮包的下載地址
- bin:二進(jìn)制發(fā)布版。
- all:bin基礎(chǔ)上還包含了源碼和文檔。
- zipStoreBase:同distributionBase,只不過存放的是zip壓縮包的
- zipStorePath:同distributionPath,只不過存放的是zip壓縮包的
gradle構(gòu)建機(jī)制
android gradle工程目錄

Gradle DSL
- DSL(Domain Specific Language) 領(lǐng)域特定語言,或領(lǐng)域?qū)僬Z言。簡單來說就是專門關(guān)注某一領(lǐng)域的語言,它在于專而不是全,最典型的比如HTML。
- Gradle可以使用Groovy DSL,專門用來開發(fā)Gradle的構(gòu)建腳本。所以說Gradle整體設(shè)計(jì)是以作為一種語言為導(dǎo)向的,并非成為一個(gè)嚴(yán)格死板的框架
settings.gradle

- Gradle支持多工程構(gòu)建,使用settings.gradle來配置添加子工程(模塊)。
- settings文件在初始化階段執(zhí)行,創(chuàng)建Settings對象,在執(zhí)行腳本時(shí)調(diào)用該對象的方法。
- Settings.include(String... projectPaths):
- 將給定的目錄添加到項(xiàng)目構(gòu)建中,':app'表示文件相對路徑,相當(dāng)于'./app'文件夾。
- 多項(xiàng)目架構(gòu)進(jìn)行分層,把同層次的子工程放在同一文件夾下便于管理,使用':xxx:yyy'表示
build.gradle
- build.gradle是項(xiàng)目構(gòu)建文件,每個(gè)工程都有一個(gè)build.gradle文件。
- build.gradle在配置階段執(zhí)行,并創(chuàng)建相應(yīng)工程的Project對象,執(zhí)行的代碼可以直接調(diào)用該對象提供的方法或?qū)傩?/li>
Daemon(守護(hù)進(jìn)程)
- 項(xiàng)目啟動(dòng)時(shí),會(huì)開啟一個(gè)client,然后啟動(dòng)一個(gè)daemon,通過client向daemon收發(fā)請求,項(xiàng)目關(guān)閉,client關(guān)閉,daemon保持啟動(dòng),有類似項(xiàng)目再次部署時(shí),會(huì)直接通過新的client訪問已經(jīng)啟動(dòng)的daemon,所以速度很快,默認(rèn)daemon不使用3小時(shí)后關(guān)閉;不同項(xiàng)目兼容性考慮,也可使用--no-daemon 啟動(dòng)項(xiàng)目,就沒有速度優(yōu)勢了
- 手動(dòng)停止daemon:gradle wrapper --stop
生命周期
- Initialization
- Gradle支持單項(xiàng)目和多項(xiàng)目構(gòu)建。在初始化階段,Gradle確定哪些項(xiàng)目參與構(gòu)建,并為每個(gè)項(xiàng)目創(chuàng)建project實(shí)例,比如解析setting.gradle
- Configuration
- 配置階段,解析每個(gè)工程的build.gradle文件,創(chuàng)建要執(zhí)行的任務(wù)子集和確定各種任務(wù)之間的關(guān)系,并對任務(wù)做一些初始化配置
- 解析過程中并不會(huì)執(zhí)行各個(gè)build.gradle中的task
- 經(jīng)過Configration階段,Project之間及內(nèi)部Task之間的關(guān)系就確定了
- 一個(gè)Project包含很多Task,每個(gè)Task之間有依賴關(guān)系。Configuration會(huì)建立一個(gè)有向圖來描述Task之間的依賴關(guān)系
- 所有Project配置完成后,會(huì)有一個(gè)回調(diào)project.afterEvaluate(),表示所有的模塊都已經(jīng)配置完了
- Execution
- 運(yùn)行階段,Gradle根據(jù)配置階段創(chuàng)建和配置要執(zhí)行的任務(wù)子集,執(zhí)行任務(wù)
執(zhí)行流程

自定義任務(wù)
task
- task是gradle中最小的任務(wù)單元,任務(wù)之間可以進(jìn)行復(fù)雜的操作(如動(dòng)態(tài)創(chuàng)建任務(wù),多任務(wù)間依賴調(diào)用等等)。gradle的執(zhí)行其實(shí)就是由各種任務(wù)組合執(zhí)行,來對項(xiàng)目進(jìn)行構(gòu)建的
- gradlew tasks -all命令查看所有任務(wù)
- gradlew A B 命令表示執(zhí)行任務(wù)A和B
自定義任務(wù)
- build.gradle中自定義任務(wù)
-
task(任務(wù)名){}
image.png
-
- { }執(zhí)行的是配置階段的代碼,執(zhí)行階段要處理的邏輯需要調(diào)用doFirst、doLast方法,在閉包中實(shí)現(xiàn)。
- doFirst{}表示任務(wù)執(zhí)行開始時(shí)調(diào)用的方法
- doLast{}表示任務(wù)執(zhí)行結(jié)束調(diào)用的方法。
- task A(dependsOn:[B]){} 表示任務(wù)A依賴于任務(wù)B,那么B執(zhí)行在A之前。
task A {
println("Hello A")
doLast {
println("doLast A")
}
}
task B {
println("Hello B")
doLast {
println("doLast B")
}
}
task test(dependsOn: [A, B]) {
doLast {
println("doLast test")
}
}
A.dependsOn(B)
- 自定義的任務(wù)默認(rèn)分組到other中。
DefaultTask
- task定義的任務(wù)其實(shí)就是DefaultTask的一種具體實(shí)現(xiàn)類的對象。
- 可以使用自定義類繼承DeaflutTask:
- 在方法上使用@TaskAction注解,表示任務(wù)運(yùn)行時(shí)調(diào)用的方法。
- 使用@Input表示對任務(wù)的輸入?yún)?shù)。
- 使用@OutputFile表示任務(wù)輸出文件。
- 使用inputs,outputs直接設(shè)置任務(wù)輸入/輸出項(xiàng)。
- 一個(gè)任務(wù)的輸出項(xiàng)可以作為另一個(gè)任務(wù)的輸入項(xiàng) (隱式依賴關(guān)系)。
獲取任務(wù)的類型
task A {
}
println(A.class)//class org.gradle.api.DefaultTask_Decorated
自定義任務(wù)類型實(shí)現(xiàn)自定義任務(wù)
-
創(chuàng)建一個(gè)自定義任務(wù)
image.png - 自定義任務(wù)實(shí)現(xiàn)文件的輸入輸出
class MyTask extends DefaultTask {
String from
File out
@TaskAction
void method() {
println "我是自定義任務(wù)"
//文件進(jìn)行操作
println inputs.files.singleFile
def inFile = inputs.files.singleFile
//將build.gradle文件復(fù)制到test文件
def outFile = outputs.files.singleFile
outFile.createNewFile()
outFile.text = inFile.text
}
}
task myTask(type: MyTask) {
from = "I am Peakmain"
out = file("test.txt")
inputs.file file('build.gradle')
outputs.file file('test.txt')
}
細(xì)心的人可能會(huì)發(fā)現(xiàn),我們執(zhí)行多次的時(shí)候并沒有打印,這是因?yàn)槲覀兊膬?nèi)容沒有改變,所以會(huì)直接跳過@TaskAction方法,如果我們想每次都執(zhí)行TaskAction怎么解決,我們可以在構(gòu)造函數(shù)中添加一行代碼
MyTask() {
outputs.upToDateWhen {
false
}
}
鉤子函數(shù)
初始化階段
android中的settings.gradle中主要是gradle的初始化,具體大家看上面Gradle執(zhí)行流程圖
gradle.projectsLoaded {
println "gradle.projectsLoaded"
}
gradle.settingsEvaluated {
println "gradle.settingsEvaluated"
}
Terminal中執(zhí)行命令:gradlew help,我們便可以看到我們的打印

配置階段
gradle對項(xiàng)目所有l(wèi)ibrary生效,project只對當(dāng)前l(fā)ibrary生效
gradle.beforeProject {
println "gradle.beforeProject"
}
gradle.afterProject {
println "gradle.afterProject"
}
//所有配置完成之后執(zhí)行
gradle.taskGraph.whenReady {
println "gradle.taskGraph.whenReady"
}
//只對當(dāng)前有效
project.beforeEvaluate {
//root無效
println "beforeEvaluate"
}
project.afterEvaluate {
println "afterEvaluate"
}
結(jié)果

gradle設(shè)置監(jiān)聽
//為gradle設(shè)置監(jiān)聽
gradle.addProjectEvaluationListener(new ProjectEvaluationListener() {
@Override
void beforeEvaluate(Project project) {
println "beforeEvaluate"
}
@Override
void afterEvaluate(Project project, ProjectState projectState) {
println "afterEvaluate"
}
})
//設(shè)置構(gòu)建監(jiān)聽
gradle.addBuildListener(new BuildListener(){
@Override
void buildStarted(Gradle gradle) {
}
@Override
void settingsEvaluated(Settings settings) {
}
@Override
void projectsLoaded(Gradle gradle) {
}
@Override
void projectsEvaluated(Gradle gradle) {
}
@Override
void buildFinished(BuildResult buildResult) {
}
})
Project
- build.gradle在配置階段會(huì)生成project實(shí)例,在build.gradle中直接調(diào)用方法或?qū)傩?,?shí)則是調(diào)用當(dāng)前工程的project對象的方法或?qū)傩?/li>
- 使用Project提供的api,更方便在多項(xiàng)目構(gòu)建設(shè)置
- project(":app"){}指定的project(這里是app)配置
- allprojects{}所有的project配置
- subprojects{}所有的子project 配置
- buildscript{}此項(xiàng)目配置構(gòu)建腳本類路徑

屬性擴(kuò)展
- 使用ext對任意對象屬性進(jìn)行擴(kuò)展
- 對project進(jìn)行使用ext進(jìn)行屬性擴(kuò)展,對所有子project可見
- 一般在root project進(jìn)行ext屬性擴(kuò)展,為子工程提供復(fù)用屬性,通過rootProject直接訪問
- 任意對象都可以使用ext來添加屬性:使用閉包,在閉包定義擴(kuò)展屬性。直接使用=賦值,添加擴(kuò)展屬性
- 由誰進(jìn)行ext調(diào)用,就屬于誰的擴(kuò)展屬性
- 在build.gradle中,默認(rèn)當(dāng)前工程的project對象,所以在build.gradle直接使用"ext="或者"ext{}"其實(shí)就是給project定義擴(kuò)展屬性
- 使用gradle.properties以鍵值對形式定義屬性,所有project可直接使用
ext{//相當(dāng)于project.ext
author="peakmain"
}
task myTask{
}
myTask.ext.username="peakmain"
println(myTask.ext.username)
println(myTask.username)
Gradle插件
腳本插件
afterEvaluate {
println tasks.getByName("packageDebug")
task zip(type: Zip) {
archiveName "outputs.zip"http:// 輸出的文件名字
destinationDir file("${buildDir}/custom")// 輸出的文件存放的文件夾
from tasks.getByName("packageDebug").outputs.files// 輸入的文件
tasks.getByName("packageDebug").outputs.files.each {
println it
}
}
}
二進(jìn)制插件
class MyTask implements Plugin<Project>{
@Override
void apply(Project project) {
println("MyTask")
}
}
apply plugin:MyTask
自定義Gradle插件,實(shí)現(xiàn)packageDebug的打包
1.新建buildSrc目錄
2.新建一個(gè)build.gradle,同步構(gòu)建一下
3.新建文件夾src/main/java
4.build.gradle引入插件
apply plugin:"java"
5.新建PeakmainPlugin.java類
public class PeakmainPlugin implements Plugin<Project> {
@Override
public void apply(Project project) {
project.afterEvaluate(it -> {
System.out.println(it.getTasks().getByName("packageDebug"));
Map<String, Class<?>> typeMap = new HashMap<>();
typeMap.put("type", Zip.class);
Zip zipTask = (Zip) project.task(typeMap, "zipDebug");
zipTask.setArchiveName("outputs.zip");
zipTask.setDestinationDir(new File(project.getBuildDir().getAbsolutePath() + "/custom"));
zipTask.from(it.getTasks().getByName("packageDebug").getOutputs().getFiles());
});
}
}
6.app目錄下的build.gradle引入插件,同步一下
apply plugin:PeakmainPlugin
7.AndroidStudio右邊的Gradle的Other多了一個(gè)zipDebug

8.結(jié)果





