關(guān)于AS中的Gradle

Gradle是干嘛的颅崩?

簡(jiǎn)單的講,Gradle是基于Groovy的項(xiàng)目自動(dòng)化構(gòu)建工具,用來(lái)聲明項(xiàng)目配置
具體一點(diǎn)戈钢,在開(kāi)發(fā)過(guò)程中主要實(shí)現(xiàn)工程的管理,例如依賴(lài),打包,部署,發(fā)布,各種渠道的差異管理是尔,Gradle負(fù)責(zé)將這些行為以代碼的方式描述出來(lái)以實(shí)現(xiàn)行為的復(fù)用

基本概念

projects , tasks and action:工程殉了,任務(wù),還有行為
一個(gè)項(xiàng)目至少要有一個(gè)工程拟枚,一個(gè)工程至少要有一個(gè)任務(wù)薪铜,一個(gè)任務(wù)由一些行為組成
結(jié)合實(shí)例來(lái)理解:
對(duì)于一個(gè)標(biāo)準(zhǔn)的AS項(xiàng)目而言,一個(gè)build.gradle對(duì)應(yīng)一個(gè)project恩溅,action則相當(dāng)于build.gradle中的一段段代碼塊
在工程構(gòu)建的過(guò)程中隔箍,gradle會(huì)根據(jù)build.gradle中的配置信息生成相應(yīng)的project和task
Project實(shí)質(zhì)上是一系列task的集合,每一個(gè)task執(zhí)行一些工作脚乡,比如編譯類(lèi)文件蜒滩,解壓縮文件,刪除文件等等

怎么用?

構(gòu)建

  • 初始化階段:首先會(huì)創(chuàng)建一個(gè)Project對(duì)象帮掉,然后執(zhí)行build.gradle配置這個(gè)對(duì)象弦悉。如果一個(gè)工程中有多個(gè)module,那么意味著會(huì)有多個(gè)Project,也就需要多個(gè)build.gradle
  • 配置階段:配置腳本會(huì)被執(zhí)行,執(zhí)行的過(guò)程中蟆炊,新的task會(huì)被創(chuàng)建并且配置給Project對(duì)象
  • 執(zhí)行階段:配置階段創(chuàng)建的task會(huì)被執(zhí)行稽莉,執(zhí)行的順序取決于啟動(dòng)腳本時(shí)傳入的參數(shù)和當(dāng)前目錄

task

task標(biāo)示一個(gè)邏輯上的執(zhí)行單元
舉幾個(gè)栗子:

  • 重新編譯工程,用到一個(gè)叫做build 的task
  • 清理工程涩搓,用到一個(gè)叫clean 的task
    ...
    具體有哪些task可已通過(guò)gradle tasks查看

自定義task

在build.gradle中定義

  • 方式1:
task haha {  
    println "HAHA"  
}  

執(zhí)行g(shù)radle haha污秆,則會(huì)打印出haha

  • 方式2:
task hello << {  
    println "hello,world"  
}  

<<意思是給hello這個(gè)task添加一些action,其實(shí)就是調(diào)用了task的doLast方法昧甘,相當(dāng)于以下:

task hello {  
    doLast{  
        println "hello良拼,world"  
    }  
}  

目前build.gradle中存在haha和hello兩個(gè)task,我們執(zhí)行一下gradle看看結(jié)果:

ckc@ckc-PC:~/AopDemo$ ./gradlew
Picked up _JAVA_OPTIONS:   -Dawt.useSystemAAFontSettings=gasp

> Configure project :
HAHA
The Task.leftShift(Closure) method has been deprecated and is scheduled to be removed in Gradle 5.0. Please use Task.doLast(Action) instead.
        at build_1wojgokbha0tm9swmixbdcemv.run(/home/ckc/AopDemo/build.gradle:33)

結(jié)果可知充边,只執(zhí)行了haha的task
這里就有兩個(gè)疑問(wèn):
1.并沒(méi)有執(zhí)行haha的task庸推,他為什么執(zhí)行了?
2.既然haha執(zhí)行了hello為神馬沒(méi)有執(zhí)行浇冰?
解釋是贬媒,方式1的定義方式生成的task是在初始化階段就會(huì)默認(rèn)執(zhí)行,而方式2是在執(zhí)行階段才會(huì)執(zhí)行
簡(jiǎn)單的講就是doLast起到的作用

  • 方式3:
// 需要繼承自DefaultTask
class HelloTask extends DefaultTask {
    // @Optional 表示在配置該Task時(shí)肘习,message是可選的际乘。
    @Optional
    String message = 'I am 34sir'
    // @TaskAction 表示該Task要執(zhí)行的動(dòng)作,即在調(diào)用該Task時(shí),hello()方法將被執(zhí)行
    @TaskAction
    def hello() {
        println "$message"
    }

    @Override
    void onlyIf(Spec<? super Task> onlyIfSpec) {

    }

    @Override
    void setOnlyIf(Spec<? super Task> onlyIfSpec) {

    }

    @Override
    Task doFirst(Action<? super Task> action) {
        return null
    }

    @Override
    Task doLast(Action<? super Task> action) {
        return null
    }

    @Override
    int compareTo(Task task) {
        return 0
    }

    @Override
    void setActions(List<Action<? super Task>> actions) {

    }
}

// hello使用了默認(rèn)的message值
task helloOne(type: HelloTask)

// 重新設(shè)置了message的值
task helloTwo(type: HelloTask) {
    message = "你站在這別動(dòng)漂佩,我去給你買(mǎi)橘子"
}

當(dāng)前工程中定義

我們可以把task定義在buildSrc module中:
在項(xiàng)目的根目錄下新建一個(gè)名為buildSrc文件夾(一定要這樣命名),然后依次新建子目錄src/main/groovy,然后可以建自己的包名脖含,這里以com.oil為例,依次新建子目錄demo/gradle/task,然后在buildSrc根目錄下新建build.gradle文件投蝉,此build.gradle中:

 apply plugin: 'groovy'

 dependencies {
    compile gradleApi()
    compile localGroovy()
}

在demo/gradle/task目錄下創(chuàng)建HelloTask.groovy文件养葵,此文件中:

import org.gradle.api.DefaultTask
import org.gradle.api.tasks.Optional
import org.gradle.api.tasks.TaskAction

class HelloThreeTask extends DefaultTask {
    @Optional
    String message = 'I am 34sir'

    @TaskAction
    def hello() {
        println "hello world $message"
    }
}

查看buildSrc下的目錄:

image.png

使用此task:
build.gradle中:

task helloThree(type: HelloThreeTask) {
    message = "hello three"
}

執(zhí)行命令:gradle helloThree
查看運(yùn)行結(jié)果:

> Task :app:helloThree
hello world hello three

自定義plugin

build.gradle中:

apply plugin: DateAndTimePlugin
dateAndTime {
    timeFormat = 'HH:mm:ss.SSS'
    dateFormat = 'MM/dd/yyyy'
}

// 每一個(gè)自定義的Plugin都需要實(shí)現(xiàn)Plugin<T>接口
class DateAndTimePlugin implements Plugin<Project> {
    //該接口定義了一個(gè)apply()方法,在該方法中墓拜,我們可以操作Project港柜,
    //比如向其中加入Task,定義額外的Property等咳榜。
    void apply(Project project) {
        println "Current time"
        project.extensions.create("dateAndTime", DateAndTimePluginExtension)
        //每個(gè)Gradle的Project都維護(hù)了一個(gè)ExtenionContainer,
        //我們可以通過(guò)project.extentions進(jìn)行訪問(wèn)
        //比如讀取額外的Property和定義額外的Property等爽锥。
        project.task('showTime') << {
            println "Current time is " + new Date().format(project.dateAndTime.timeFormat)
        }

        project.tasks.create('showDate') << {
            println "Current date is " + new Date().format(project.dateAndTime.dateFormat)
        }
    }
}
//向Project中定義了一個(gè)名為dateAndTime的extension
//并向其中加入了2個(gè)Property涌韩,分別為timeFormat和dateFormat
class DateAndTimePluginExtension {
    String timeFormat = "MM/dd/yyyyHH:mm:ss.SSS"
    String dateFormat = "yyyy-MM-dd"
}

執(zhí)行gradle showTime以及gradle showDate查看結(jié)果:

> Task :app:showTime
Current time is 14:52:11.539
> Task :app:showDate
Current date is 02/08/2018

執(zhí)行task

執(zhí)行多個(gè)task

gradle task1 task2 [...]

簡(jiǎn)化執(zhí)行

對(duì)于名字太長(zhǎng)的task可以簡(jiǎn)化執(zhí)行
例如上面的hello就可以這樣執(zhí)行:

gradle hell //能唯一標(biāo)識(shí)出task的字符串即可

自動(dòng)執(zhí)行任務(wù)

不想在每次打包前執(zhí)行各種自定義的任務(wù),我們可以在build時(shí)自動(dòng)執(zhí)行任務(wù):

afterEvaluate {
    tasks.matching {
        // 以process開(kāi)頭以ReleaseJavaRes或DebugJavaRes結(jié)尾的task
        it.name.startsWith('process') && (it.name.endsWith('ReleaseJavaRes') || it.name.endsWith
                ('DebugJavaRes'))
   }.each { task ->
        task.dependsOn(chVer, chSo)  // 任務(wù)依賴(lài):執(zhí)行task之前需要執(zhí)行dependsOn指定的任務(wù)
    }
}

type

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

以上這段task想必大家都見(jiàn)過(guò)氯夷,這里出現(xiàn)了一個(gè)新的概念:type
task的有很多中類(lèi)型臣樱,此處的類(lèi)型就是delete,任務(wù)是刪除文件

常見(jiàn)的type

  • Copy
    將文件復(fù)制到目標(biāo)目錄,同時(shí)雇毫,也可以執(zhí)行重命名和過(guò)濾文件操作

替換AndroidManifest文件:

task chVer(type: Copy) { // 指定Type為Copy任務(wù)
    from "src/main/manifest/AndroidManifestCopy.xml"  // 復(fù)制src/main/manifest/目錄下的AndroidManifest.xml
    into 'src/main'  // 復(fù)制到指定目標(biāo)目錄
    rename { String fileName -> //在復(fù)制時(shí)重命名文件
        fileName = "AndroidManifest.xml" // 重命名
    }
}

替換so文件:

task chSo(type: Copy) {
    from "src/main/jniLibs/test"   // 復(fù)制test文件夾下的所有so文件
    into "src/main/jniLibs/armeabi-v7a" //復(fù)制到armeabi-v7a文件夾下
}
  • Sync
    與Copy任務(wù)類(lèi)似玄捕,唯一的區(qū)別是當(dāng)執(zhí)行時(shí)會(huì)復(fù)制源文件到目標(biāo)目錄,目標(biāo)目錄中所有非復(fù)制文件將會(huì)被刪除棚放,除非指定Sync.preserve(org.gradle.api.Action)
task syncDependencies(type: Sync) {
    from 'my/shared/dependencyDir'
    into 'build/deps/compile'
}

// 你可以保護(hù)目標(biāo)目錄已經(jīng)存在的文件枚粘。匹配的文件將不會(huì)被刪除。
task sync(type: Sync) {
    from 'source'
    into 'dest'
    preserve {
        include 'extraDir/**'
        include 'dir1/**'
        exclude 'dir1/extra.txt'
    }
}
  • Zip
    創(chuàng)建ZIP歸檔文件飘蚯,默認(rèn)壓縮文件類(lèi)型為zip
task zip(type: Zip) {
    from 'src/dist'
    into('libs') 
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末馍迄,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子局骤,更是在濱河造成了極大的恐慌攀圈,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,907評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件峦甩,死亡現(xiàn)場(chǎng)離奇詭異赘来,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)凯傲,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,987評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)犬辰,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人泣洞,你說(shuō)我怎么就攤上這事忧风。” “怎么了球凰?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,298評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵狮腿,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我呕诉,道長(zhǎng)缘厢,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,586評(píng)論 1 293
  • 正文 為了忘掉前任甩挫,我火速辦了婚禮贴硫,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘伊者。我一直安慰自己英遭,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,633評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布亦渗。 她就那樣靜靜地躺著挖诸,像睡著了一般。 火紅的嫁衣襯著肌膚如雪法精。 梳的紋絲不亂的頭發(fā)上多律,一...
    開(kāi)封第一講書(shū)人閱讀 51,488評(píng)論 1 302
  • 那天痴突,我揣著相機(jī)與錄音,去河邊找鬼狼荞。 笑死辽装,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的相味。 我是一名探鬼主播拾积,決...
    沈念sama閱讀 40,275評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼攻走!你這毒婦竟也來(lái)了殷勘?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,176評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤昔搂,失蹤者是張志新(化名)和其女友劉穎玲销,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體摘符,經(jīng)...
    沈念sama閱讀 45,619評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡贤斜,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,819評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了逛裤。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片瘩绒。...
    茶點(diǎn)故事閱讀 39,932評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖带族,靈堂內(nèi)的尸體忽然破棺而出锁荔,到底是詐尸還是另有隱情,我是刑警寧澤蝙砌,帶...
    沈念sama閱讀 35,655評(píng)論 5 346
  • 正文 年R本政府宣布阳堕,位于F島的核電站,受9級(jí)特大地震影響择克,放射性物質(zhì)發(fā)生泄漏恬总。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,265評(píng)論 3 329
  • 文/蒙蒙 一肚邢、第九天 我趴在偏房一處隱蔽的房頂上張望壹堰。 院中可真熱鬧,春花似錦骡湖、人聲如沸贱纠。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,871評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)并巍。三九已至,卻和暖如春换途,著一層夾襖步出監(jiān)牢的瞬間懊渡,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,994評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工军拟, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留剃执,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,095評(píng)論 3 370
  • 正文 我出身青樓懈息,卻偏偏與公主長(zhǎng)得像肾档,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子辫继,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,884評(píng)論 2 354