Gradle系列(二) Gradle執(zhí)行順序和task

0. 前情提示

Gradle系列已完成,專注于Gradle,有如下幾篇文章

1. 什么是gradle

維基百科:Gradle是一個(gè)基于Apache Ant和Apache Maven概念的項(xiàng)目自動(dòng)化建構(gòu)工具痘绎。它使用一種基于Groovy的特定領(lǐng)域語言來聲明項(xiàng)目設(shè)置乘寒,而不是傳統(tǒng)的XML粪糙。當(dāng)前其支持的語言限于Java噪矛、Groovy和Scala,計(jì)劃未來將支持更多的語言胡诗。

按我的理解,通俗一點(diǎn)講,就是拿來構(gòu)建項(xiàng)目的,我們平時(shí)在Android Studio上開發(fā)Android項(xiàng)目就是用Gradle進(jìn)行構(gòu)建的,相比于傳統(tǒng)的xml方式,我感覺更加靈活.畢竟,可以寫代碼,根據(jù)不同的環(huán)境搞些騷操作.

gradle里面其實(shí)需要學(xué)習(xí)的有3個(gè)

剛哥說過,遇到不會(huì)的直接查官方文檔,不要每次去搜索引擎東搜西搜,這樣效率很低.

這里插播一個(gè)小知識(shí)點(diǎn),如何查詢官方文檔.比如在gradle中經(jīng)常用的buildscript到底是什么?來到官方文檔首頁,點(diǎn)開頂部INDEX,搜索buildscript,即可找到這個(gè)東西是解釋.

2. gradle項(xiàng)目結(jié)構(gòu)

首先我們來新建一個(gè)Android項(xiàng)目,什么都不要?jiǎng)?

QZLQBT.png
  • 最外層setting.gradle為根項(xiàng)目的配置,可以知道需要包含哪些模塊,然后最外層的build.gralde也是根項(xiàng)目的配置.模塊中的build.gradle是子項(xiàng)目的配置.
  • gradle文件夾下面是版本配置以及gradle所需要的腳本
  • 最外層的gradlew為linux/mac下的腳本,gradlew.bat是windows下面用的腳本

3. gradle配置順序

簡單在gradle中輸出語句,看看配置順序

//settings.gradle
println("setting 開始配置")
include ':app'
rootProject.name='Hello'
println("setting 配置完成")
//project build.gradle
println("根build.gradle 開始配置")
buildscript {
    repositories {
    }
    dependencies {
    }
}
println("根build.gradle 配置完成")
//app build.gradle
println("app build.gradle 開始配置")

project.afterEvaluate {
    println "所有模塊都已配置完成"
}

android {
    defaultConfig {
    }
    buildTypes {
    }
}

dependencies {
}
println("app build.gradle 配置完成")

打印語句寫好后,clean Project,即可執(zhí)行,輸出如下:

setting 開始配置
setting 配置完成

> Configure project :
根build.gradle 開始配置
根build.gradle 配置完成

> Configure project :app
app build.gradle 開始配置
app build.gradle 配置完成
所有模塊都已配置完成

可以看到首先是配置setting,知道有哪些模塊.然后是配置根項(xiàng)目的build.gradle,然后才是子項(xiàng)目的build.gradle配置.

我在上面加了一個(gè)監(jiān)聽器project.afterEvaluate,可以通過查詢官方文檔了解它的詳細(xì)內(nèi)容,這是一個(gè)當(dāng)所有的模塊都配置完了的時(shí)候的回調(diào).

其中,還可以在settings.gradle中添加一個(gè)監(jiān)聽器

gradle.addBuildListener(new BuildListener() {
    @Override
    void buildStarted(Gradle gradle) {
        println("buildStarted------------")
    }

    @Override
    void settingsEvaluated(Settings settings) {
        println("settingsEvaluated------------")
    }

    @Override
    void projectsLoaded(Gradle gradle) {
        println("projectsLoaded------------")
    }

    @Override
    void projectsEvaluated(Gradle gradle) {
        println("projectsEvaluated------------")
    }

    @Override
    void buildFinished(BuildResult result) {
        println("buildFinished------------")
    }
})

在執(zhí)行構(gòu)建的時(shí)候,這個(gè)監(jiān)聽器會(huì)監(jiān)聽到主要的生命周期事件,看名字大概就能大概猜出是什么意思,buildStarted已過時(shí).也可以看看官方文檔詳細(xì)了解

加入之后打印如下:

setting 開始配置
setting 配置完成
settingsEvaluated------------
projectsLoaded------------

> Configure project :
根build.gradle 開始配置
根build.gradle 配置完成

> Configure project :app
app build.gradle 開始配置
app build.gradle 配置完成
所有模塊都已配置完成
projectsEvaluated------------

buildFinished------------

4. gradle task

4.1 初識(shí)task

gradle中所有的構(gòu)建工作都是由task完成的,它幫我們處理了很多工作,比如編譯,打包,發(fā)布等都是task.我們可以在項(xiàng)目的根目錄下,打開命令行(AS自帶,底部有Terminal,打開就行)執(zhí)行gradlew tasks查看當(dāng)前項(xiàng)目所有的task.

在命令行如果執(zhí)行失敗,則將項(xiàng)目的JDK location設(shè)置成本地jdk的路徑,而且jdk的版本還需要是java 8. 我用的jdk版本是1.8.0_231.

> Task :tasks

------------------------------------------------------------
Tasks runnable from root project
------------------------------------------------------------

Android tasks
-------------
androidDependencies - Displays the Android dependencies of the project.
signingReport - Displays the signing info for the base and test modules
sourceSets - Prints out all the source sets defined in this project.

Build tasks
-----------
assemble - Assemble main outputs for all the variants.
assembleAndroidTest - Assembles all the Test applications.
build - Assembles and tests this project.
buildDependents - Assembles and tests this project and all projects that depend on it.
buildNeeded - Assembles and tests this project and all projects it depends on.
bundle - Assemble bundles for all the variants.
clean - Deletes the build directory.
cleanBuildCache - Deletes the build cache directory.
compileDebugAndroidTestSources
compileDebugSources
compileDebugUnitTestSources
compileReleaseSources
compileReleaseUnitTestSources

Build Setup tasks
-----------------
init - Initializes a new Gradle build.
wrapper - Generates Gradle wrapper files.

Cleanup tasks
-------------
lintFix - Runs lint on all variants and applies any safe suggestions to the source code.

Help tasks
----------
buildEnvironment - Displays all buildscript dependencies declared in root project 'Hello'.
components - Displays the components produced by root project 'Hello'. [incubating]
dependencies - Displays all dependencies declared in root project 'Hello'.
dependencyInsight - Displays the insight into a specific dependency in root project 'Hello'.
dependentComponents - Displays the dependent components of components in root project 'Hello'. [incubating]
help - Displays a help message.
model - Displays the configuration model of root project 'Hello'. [incubating]
projects - Displays the sub-projects of root project 'Hello'.
properties - Displays the properties of root project 'Hello'.
tasks - Displays the tasks runnable from root project 'Hello' (some of the displayed tasks may belong to subprojects).

Install tasks
-------------
installDebug - Installs the Debug build.
installDebugAndroidTest - Installs the android (on device) tests for the Debug build.
uninstallAll - Uninstall all applications.
uninstallDebug - Uninstalls the Debug build.
uninstallDebugAndroidTest - Uninstalls the android (on device) tests for the Debug build.
uninstallRelease - Uninstalls the Release build.

Verification tasks
------------------
check - Runs all checks.
connectedAndroidTest - Installs and runs instrumentation tests for all flavors on connected devices.
connectedCheck - Runs all device checks on currently connected devices.
connectedDebugAndroidTest - Installs and runs the tests for debug on connected devices.
deviceAndroidTest - Installs and runs instrumentation tests using all Device Providers.
deviceCheck - Runs all device checks using Device Providers and Test Servers.
lint - Runs lint on all variants.
lintDebug - Runs lint on the Debug build.
lintRelease - Runs lint on the Release build.
lintVitalRelease - Runs lint on just the fatal issues in the release build.
test - Run unit tests for all variants.
testDebugUnitTest - Run unit tests for the debug build.
testReleaseUnitTest - Run unit tests for the release build.

To see all tasks and more detail, run gradlew tasks --all

可以看到,這里有很多的task.比如我們?cè)诿钚袌?zhí)行gradlew clean就是clean.執(zhí)行gradlew installDebug就是構(gòu)建debug項(xiàng)目然后安裝到手機(jī)上.

4.2 編寫task

書寫task非常簡單,比如我們?cè)诟夸浀腷uild.gradle中加入一個(gè)hello的task

task hello() {
    println "hello world"

    //將給定的閉包 添加到此task操作鏈表的開頭
    doFirst {
        println "hello task doFirst"
    }

    doLast {
        println "hello task doLast"
    }
}

然后在命令行執(zhí)行gradlew hello,輸出如下

setting 開始配置
setting 配置完成

> Configure project :
根build.gradle 開始配置
hello world
根build.gradle 配置完成

> Configure project :app
app build.gradle 開始配置
app build.gradle 配置完成

> Task :hello
hello task doFirst
hello task doLast

它會(huì)先配置完成,才會(huì)執(zhí)行.在一個(gè)task內(nèi)部其實(shí)擁有一個(gè)action列表,執(zhí)行的時(shí)候其實(shí)就是執(zhí)行這個(gè)列表,它的類型是一個(gè)List.上面的doFirst和doLast就是創(chuàng)建action的兩個(gè)方法,文檔.doFirst是在最開始執(zhí)行,doLast是在最后執(zhí)行,大括號(hào)里面?zhèn)魅氲氖情]包.

4.3 task執(zhí)行順序

task是有執(zhí)行順序的,在創(chuàng)建完Android項(xiàng)目之后,根目錄下的build.gradle中,有一個(gè)clean的task.這個(gè)是AS自動(dòng)給我們生成的.

task clean(type: Delete) {
    delete rootProject.buildDir
}

我們先在根目錄下創(chuàng)建test.txt文件,然后我們?cè)谶@個(gè)task中做一些改動(dòng),執(zhí)行到clean這個(gè)task時(shí)刪除根目錄下的test.txt文件.

task clean(type: Delete) {
    delete rootProject.buildDir

    doLast {
        def file = new File('test.txt')
        delete file
        println "清理"
    }
}

然后我們?cè)趆ello這個(gè)task的下面寫上

hello.dependsOn clean

這樣就表示hello這個(gè)task依賴clean這個(gè)task,當(dāng)執(zhí)行hello這個(gè)task時(shí)需要先執(zhí)行clean.
我們?cè)诿钚袌?zhí)行gradlew hello看看是不是這樣.我執(zhí)行之后它的輸出是

> Task :clean
清理

> Task :hello
hello task doFirst
hello task doLast

先執(zhí)行clean,再執(zhí)行hello這個(gè)task.而且還看到test.txt文件被刪除(如果看到?jīng)]刪除,刷新一下看看)了,那么說明確實(shí)是clean先執(zhí)行.

這個(gè)順序有什么用?其實(shí)是很有用的,比如執(zhí)行安裝task的時(shí)候,肯定會(huì)先執(zhí)行編譯,打包這些步驟.

4.4 自帶 gradle task

當(dāng)我們?cè)贏S中創(chuàng)建Android項(xiàng)目的時(shí)候,默認(rèn)會(huì)帶一些Android的一些gradle task,這些task都是gradle和Android Gradle Plugin給我們創(chuàng)建好的,可以直接用.

Qe1fy9.png

比如我們上面使用到的gradlew clean是用來清理項(xiàng)目的.和編譯相關(guān)的task主要有:build和assemble居暖,其中build依賴assemble,也就是說執(zhí)行build之前會(huì)先執(zhí)行assemble菱蔬。在Android上,會(huì)根據(jù)buildType和productFlavor的不同自動(dòng)創(chuàng)建多個(gè)assembleXxx任務(wù)荒辕,如assembleDebug汗销,assembleRelease等犹褒,assemble會(huì)依賴所有的assembleXxx任務(wù)抵窒,也就是說執(zhí)行assemble會(huì)先執(zhí)行assembleDebug,assembleRelease等一系列的assemble任務(wù)叠骑。

如果想看Android Gradle Plugin源碼,可以在app/build.gradle中的dependencies下面引入

compileOnly 'com.android.tools.build:gradle:3.5.2'

然后就可以在項(xiàng)目的External Libraries中看到該jar的源碼,

QeUB5R.png

比如clean這個(gè)task是在com.android.build.gradle.tasks.CleanBuildCache.java里面定義的

@TaskAction
public void clean() throws IOException {
    Preconditions.checkNotNull(buildCache, "buildCache must not be null");
    buildCache.delete();
}

通過查詢gradle官方文檔可知,@TaskAction的作用:Marks a method as the action to run when the task is executed. 將方法標(biāo)記為執(zhí)行任務(wù)時(shí)要運(yùn)行的動(dòng)作.

5.Build script blocks

還有一個(gè)東西,就是幾乎每個(gè)項(xiàng)目都需要用到的地方,但是我之前卻根本不知道它真正的名字.就是Build script blocks,打開項(xiàng)目的根目錄的build.gradle文件.

buildscript {
    repositories {
        google()
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.5.2'
    }
}

allprojects {
    repositories {
        google()
        jcenter()
    }
}

每個(gè)項(xiàng)目都需要配置這些東西,但是我們真的知道他們的含義么?

首先是buildscript,查詢文檔可知:

void buildscript?(Closure configureClosure)

Configures the build script classpath for this project.

The given closure is executed against this project's ScriptHandler. The ScriptHandler is passed to the closure as the closure's delegate.

為該項(xiàng)目配置構(gòu)建腳本類路徑.參數(shù)是Closure,閉包.這個(gè)閉包是委托給了ScriptHandler,又去看看ScriptHandler

dependencies?(Closure configureClosure)  Configures the dependencies for the script.
repositories?(Closure configureClosure)   Configures the repositories for the script dependencies.

dependencies?是添加編譯依賴項(xiàng)的,repositories?是為腳本依賴項(xiàng)配置存儲(chǔ)庫.他們的配置,都是用閉包的形式.

然后dependencies?又是委托了DependencyHandler進(jìn)行配置,對(duì)于怎么配置,官方還給了示例

Example shows a basic way of declaring dependencies.

 apply plugin: 'java'
 //so that we can use 'implementation', 'testImplementation' for dependencies

 dependencies {
   //for dependencies found in artifact repositories you can use
   //the group:name:version notation
   implementation 'commons-lang:commons-lang:2.6'
   testImplementation 'org.mockito:mockito:1.9.0-rc1'

   //map-style notation:
   implementation group: 'com.google.code.guice', name: 'guice', version: '1.0'

   //declaring arbitrary files as dependencies
   implementation files('hibernate.jar', 'libs/spring.jar')

   //putting all jars from 'libs' onto compile classpath
   implementation fileTree('libs')
 }

6. 總結(jié)

本文帶大家梳理了Gradle的執(zhí)行順序,Task和Build script blocks這些知識(shí)點(diǎn).為了更好的認(rèn)識(shí)Gradle.現(xiàn)在對(duì)Gradle了解又深了一步,而且如果以后遇到不懂的還知道到哪里去查文檔,方便快捷,不用再到處搜了.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末李皇,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子宙枷,更是在濱河造成了極大的恐慌掉房,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,464評(píng)論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件慰丛,死亡現(xiàn)場離奇詭異卓囚,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)诅病,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,033評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門哪亿,熙熙樓的掌柜王于貴愁眉苦臉地迎上來粥烁,“玉大人,你說我怎么就攤上這事蝇棉√肿瑁” “怎么了?”我有些...
    開封第一講書人閱讀 169,078評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵篡殷,是天一觀的道長钝吮。 經(jīng)常有香客問我,道長板辽,這世上最難降的妖魔是什么奇瘦? 我笑而不...
    開封第一講書人閱讀 59,979評(píng)論 1 299
  • 正文 為了忘掉前任,我火速辦了婚禮劲弦,結(jié)果婚禮上链患,老公的妹妹穿的比我還像新娘。我一直安慰自己瓶您,他們只是感情好麻捻,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,001評(píng)論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著呀袱,像睡著了一般贸毕。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上夜赵,一...
    開封第一講書人閱讀 52,584評(píng)論 1 312
  • 那天明棍,我揣著相機(jī)與錄音,去河邊找鬼寇僧。 笑死摊腋,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的嘁傀。 我是一名探鬼主播兴蒸,決...
    沈念sama閱讀 41,085評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼细办!你這毒婦竟也來了橙凳?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 40,023評(píng)論 0 277
  • 序言:老撾萬榮一對(duì)情侶失蹤笑撞,失蹤者是張志新(化名)和其女友劉穎岛啸,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體茴肥,經(jīng)...
    沈念sama閱讀 46,555評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡坚踩,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,626評(píng)論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了瓤狐。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片瞬铸。...
    茶點(diǎn)故事閱讀 40,769評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡卧晓,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出赴捞,到底是詐尸還是另有隱情逼裆,我是刑警寧澤,帶...
    沈念sama閱讀 36,439評(píng)論 5 351
  • 正文 年R本政府宣布赦政,位于F島的核電站胜宇,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏恢着。R本人自食惡果不足惜桐愉,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,115評(píng)論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望掰派。 院中可真熱鬧从诲,春花似錦、人聲如沸靡羡。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,601評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽略步。三九已至描扯,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間趟薄,已是汗流浹背绽诚。 一陣腳步聲響...
    開封第一講書人閱讀 33,702評(píng)論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留杭煎,地道東北人恩够。 一個(gè)月前我還...
    沈念sama閱讀 49,191評(píng)論 3 378
  • 正文 我出身青樓,卻偏偏與公主長得像羡铲,于是被迫代替她去往敵國和親蜂桶。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,781評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容

  • 版權(quán)聲明:本文為博主原創(chuàng)文章犀勒,未經(jīng)博主允許不得轉(zhuǎn)載屎飘。 https://blog.csdn.net/zhaoyanj...
    勤奮的pangdunhu閱讀 2,044評(píng)論 0 1
  • Gradle簡介 Gradle是一個(gè)構(gòu)建工具,同時(shí)它也是一個(gè)編程框架贾费。 當(dāng)你把Gradle當(dāng)構(gòu)建工具看的時(shí)候,我們...
    Rangethan閱讀 2,322評(píng)論 1 8
  • 參考資料:http://gold.xitu.io/post/580c85768ac247005b5472f9htt...
    zhaoyubetter閱讀 11,003評(píng)論 0 6
  • 轉(zhuǎn)至:http://blog.csdn.net/heqiangflytosky/article/details/5...
    kkgo閱讀 2,886評(píng)論 0 1
  • 轉(zhuǎn)載(未找到原始鏈接) Gradle是一種構(gòu)建工具檐盟,它拋棄了基于XML的構(gòu)建腳本褂萧,取而代之的是采用一種基于Gro...
    GYLEE閱讀 4,072評(píng)論 0 2