Gradle終于懂了(一)帶你玩轉(zhuǎn)Project

本打算用gradle嘗試著去寫(xiě)一些腳本方便項(xiàng)目的構(gòu)建和打包,但是在復(fù)習(xí)gradle的時(shí)候有了一些新的理解,對(duì)gradle的理解不敢說(shuō)精通,但也更透徹了,可以說(shuō)是現(xiàn)在終于會(huì)寫(xiě)gradle了,所以打算從新寫(xiě)一個(gè)系列的文章來(lái)做個(gè)總結(jié)。
之前也發(fā)布過(guò)一些關(guān)于gradle的文章
淺談Gradle(一)
淺談Gradle(二)與SourceSet
Gradle排除依賴(lài)模塊的某個(gè)類(lèi)
Gradle自定義插件實(shí)現(xiàn)自定義Task
不要急,我不是讓你去看這些東西,我是覺(jué)得當(dāng)我回頭去看以前寫(xiě)的這些東西,真的就是弟弟,那都是看大量別人的文章之后總結(jié)寫(xiě)出的,那也是別人的東西,怎么說(shuō)呢,學(xué)了之后還是一種似懂非懂的感覺(jué)。這次不一樣,這次我是看這個(gè)來(lái)寫(xiě)的,絕對(duì)權(quán)威絕對(duì)官方 https://docs.gradle.org/current/dsl/index.html,因?yàn)樗緛?lái)就是官方。

一. 瀏覽Gradle官方文檔

機(jī)翻之后的頁(yè)面

看到有很多內(nèi)容,因?yàn)椴恢褂衋ndroid用到gradle嘛,左邊還有個(gè)目錄,入門(mén)那些的我們就不管了,進(jìn)階的也不管了,畢竟看到這里的多多少少也是寫(xiě)過(guò)一些gradle代碼的,這章我們主要看這兩個(gè)


二. gradle構(gòu)建的生命周期

先簡(jiǎn)單講講生命周期吧,一些簡(jiǎn)單的東西我就不講很詳細(xì)了,比如一個(gè)項(xiàng)目有settings.gradle、根目錄的build.gradle和模塊build.gradle這些,就不詳細(xì)講了。
看官網(wǎng)給出的介紹

機(jī)翻看得變扭,就不翻譯了

看不懂沒(méi)關(guān)系,至少我們能肯定的是構(gòu)建過(guò)程有3個(gè)生命周期,Initialization、Configuration和Execution,我建議記住這3個(gè)單詞,而不要總用中文的初始化、構(gòu)建、執(zhí)行去理解。官網(wǎng)下了還良心的給出了個(gè)Demo,告訴我們每個(gè)生命周期執(zhí)行的階段

我不會(huì)kotlin所以就只講groovy,其實(shí)差不多的。
Initialization階段會(huì)執(zhí)行settings里面的代碼,Configuration階段會(huì)執(zhí)行所有build.gradle里面的操作,無(wú)論是不是task,Execution階段會(huì)執(zhí)行action里面的操作(不懂什么是task什么是action的也別急,這里先了解下,往后學(xué)就知道了)所以這個(gè)Demo下面的內(nèi)容我們不看,學(xué)其它的東西再回來(lái)看就豁然開(kāi)朗了。

三. Project

我們直接講Project,我記得我剛學(xué)gradle的時(shí)候經(jīng)常看到有人寫(xiě)文章說(shuō)gradle最重要的是Project、task和action,其實(shí)這樣說(shuō)確實(shí)能讓新人很容易上手,卻同樣也很容易誤導(dǎo)別人。
但是從Project入手是不會(huì)有錯(cuò)的,真的了解Project是什么之后,你就真正的能看出gradle的架構(gòu),到時(shí)候task、action什么的就一目了然了。
在上面截圖的地方點(diǎn)擊進(jìn)入DSL參考



進(jìn)來(lái)后左邊目錄有什么 Build script blocks、Core types、 Publishing types、 Container types 之類(lèi)的,內(nèi)容很多,但是我們都不管,我們就看project,點(diǎn)擊project




進(jìn)來(lái)之后看到Project下面有些概念,英文不好的朋友可以翻譯看看這些概念,但是還是要記住他們的單詞。
1. project基本概念

(1)Lifecycle 生命周期
(2)Tasks 任務(wù)
(3)Dependencies 依賴(lài)
(4)Multi-project Builds 多項(xiàng)目構(gòu)建
(5)Plugins 插件
(6)Properties 屬性
(9)Methods 方法

2. 生命周期

生命周期是說(shuō),project在Initialization階段被創(chuàng)建,我們經(jīng)常在settings.gradle寫(xiě)比如

include ':app'

在Initialization階段執(zhí)行這行代碼,創(chuàng)建app這個(gè)模塊的project對(duì)象,那就是說(shuō)一般來(lái)說(shuō),每個(gè)module對(duì)應(yīng)一個(gè)project對(duì)象。準(zhǔn)確來(lái)說(shuō)是gradle根據(jù)settings.gradle去找對(duì)應(yīng)module的build.gradle來(lái)創(chuàng)建project對(duì)象,也就是說(shuō)project就是build.gradle。
所以project對(duì)象對(duì)應(yīng)的代碼在哪寫(xiě),project在哪里創(chuàng)建,這些應(yīng)該都很清楚了。

3. Methods 方法

task放到之后再寫(xiě),我更傾向于單獨(dú)拿一章出來(lái)寫(xiě),其它的也應(yīng)該分出來(lái)講,要從淺入深,所以先講Methods,因?yàn)樗?jiǎn)單。
把project當(dāng)成一個(gè)對(duì)象,那這個(gè)對(duì)象里面有方法就很容易理解吧,先看看一般AS生成的build.gradle是怎樣的,也就是project一般是怎樣的(我隨便找個(gè)Demo里面的app模塊的代碼)

apply plugin: 'com.android.application'

android {
    compileSdkVersion 27
    buildToolsVersion "27.0.0"
    defaultConfig {
        applicationId "com.tencent.tmgp.yybtestsdk"
        minSdkVersion 14
        targetSdkVersion 27
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar','*.aar'])
}

我們先不要看android {......}里面的內(nèi)容,這是plugin(插件)的知識(shí),過(guò)濾掉之后

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar','*.aar'])
}

是的,整個(gè)project里面只剩一個(gè)dependencies 方法,這里多嘴說(shuō)一下,為什么說(shuō)是方法。這個(gè)是一個(gè)閉包的寫(xiě)法,不知道的話(huà)建議先看看groovy語(yǔ)法中的閉包,一個(gè)參數(shù)的情況下是能省略括號(hào)的。

然后看看project中有什么方法,其實(shí)還挺多的

只截了一部分

截圖截不完,具體的可以看官網(wǎng)的API https://docs.gradle.org/current/javadoc/org/gradle/api/Project.html
我們隨便拿一個(gè)方法來(lái)說(shuō),比如說(shuō)getName,獲取project的名稱(chēng)
就這樣寫(xiě)

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar','*.aar'])
}

println this.getName()

this就是指這個(gè)project嘛,代碼會(huì)在Configuration生命周期中執(zhí)行,打印



嗯,我這個(gè)Module的名稱(chēng)就叫app,看得不過(guò)癮沒(méi)關(guān)系,我們可以再演示調(diào)用多一點(diǎn)的方法

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar','*.aar'])
}

println this.getName()
println this.getPath()
println this.getRootDir()
println this.getVersion()

打印結(jié)果



而且也能在文檔中找到默認(rèn)生成的dependencies



看到了吧,傳的參數(shù)是一個(gè)閉包(至于閉包里面寫(xiě)什么內(nèi)容,那就要參照官網(wǎng)文檔了)
再比如文檔中還有個(gè)ant?(Closure configureClosure)方法,那你就能這樣寫(xiě)
dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar','*.aar'])
}

ant{
  ...........
}

那是不是只能在build.gradle里面調(diào)用文檔中的方法,當(dāng)然不是,當(dāng)然也可以自己定義方法

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar','*.aar'])
}

println this.getName()
println this.getPath()
println this.getRootDir()
println this.getVersion()

// 定義一個(gè)打印的方法
def myfuction(String msg){
    println msg
}
myfuction("6666666")

看結(jié)果


上面演示的是在自己內(nèi)部調(diào)用自己的project方法,那在別的project對(duì)象中調(diào)用該project的方法呢?怎么有點(diǎn)繞,就是一號(hào)project調(diào)用二號(hào)project的方法,要怎么操作。
(為了節(jié)省時(shí)間,我拿我一個(gè)項(xiàng)目來(lái)說(shuō),這種情況肯定是多模塊的情況)

我們先理一下思路,要在一個(gè)project調(diào)用另一個(gè)project的方法要怎么做?當(dāng)然是先拿到這個(gè)project對(duì)象,然后再調(diào)用它的方法。這時(shí)候我們API找到對(duì)project的操作(多說(shuō)一句,看API最好看Javadoc)





比較分散,可能沒(méi)截完全部,總之在這個(gè)API中肯定是能找到的,光看上面的這些方法就知道能拿到所有能獲取到的Project,簡(jiǎn)單說(shuō)幾個(gè)
(1)比如getAllprojects(),返回當(dāng)前的project和子project的集合(子project的意思是比如Moudule的project就是根目錄project的子project)
(2)比如getParent()就是獲取父project
(3)比如project?(String path)就是根據(jù)path獲取project,有的人會(huì)問(wèn)我怎么懂path是什么,沒(méi)關(guān)系,你可以在對(duì)應(yīng)的project中調(diào)用getPath()打印,就知道這個(gè)project的path是什么了(一般都是:app)。
還有很多方法能獲取到相對(duì)應(yīng)的project。
假如我在名為test的project中調(diào)用:app的project

println "測(cè)試 "+project(":app").getRootDir()

獲取:app的根目錄的地址,這樣就行了,看得出什么不。
project(":app").getRootDir() 和 this,getRootDir() 得到的結(jié)果是一樣的,因?yàn)樗麄兌际峭粋€(gè)根目錄下。

4. Properties

文檔中也有個(gè)Properties文檔



截不完圖,詳細(xì)的可以看文檔,比如屬性中有個(gè)常用的屬性name,可以直接在project中獲取。

println "屬性name "+name

如果我們直接設(shè)值的話(huà)呢

name = "mytest"
println this.getName()

會(huì)提示這個(gè)屬性是只讀的屬性。
想看關(guān)于這些屬性更詳細(xì)的信息的話(huà),可以在文檔下面找到Property details


只截取一部分圖

你會(huì)發(fā)現(xiàn)屬性后面有個(gè)只讀的提示,name屬性也是,所以無(wú)法直接這樣修改屬性。

還有有個(gè)額外屬性操作,就是ext關(guān)鍵字。
在A的project中定義

ext.testStr = "test 66666666666666"

在B的project中調(diào)用

println project(":app").ext.testStr

這里先簡(jiǎn)單了解下這些原有的屬性就行,在講到插件的時(shí)候會(huì)解釋更多。

project就大概先提到這些吧,其它內(nèi)容在講到task、dependencies和plugin也會(huì)提到一些相關(guān)的內(nèi)容,學(xué)了project的生命周期和一些屬性、方法之后,對(duì)project相信也會(huì)有一定的了解。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀(guān)點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容