深入淺出聊聊Gradle三兩事

前一段時間看到不少人在技術(shù)論壇里問「剛學(xué) Android 不久光稼,對 Gradle 不懂沉唠,看了很多資料依然一知半解」奏赘,一時手癢對Gradle做了一些入門的整理竹揍,希望對大家有幫助!

說到Gradle 痕鳍,Gradle是一種構(gòu)建工具硫豆,它拋棄了基于XML的構(gòu)建腳本,取而代之的是采用一種基于Groovy的內(nèi)部領(lǐng)域特定語言笼呆。近期册舞,Gradle獲得了極大的關(guān)注宙刘,這也是我決定去研究Gradle的原因搪锣。

這篇教程講授了三部分內(nèi)容:

簡單了解一下Gradle的基礎(chǔ)Groovy 語言

理解Gradle構(gòu)建的一些基本知識

理解Gradle在實際過程中的用途及應(yīng)用

一. Groovy

Groovy 是沒有類型的 Java 代碼 ,語法更簡潔被饿,形式有點類似腳本語言,是被gradle用于構(gòu)建腳本的語言

(一)特殊類型

1铭若、范圍

范圍 是一系列的值洪碳。例如 “0..4” 表明包含 整數(shù) 0、1奥喻、2偶宫、3、4环鲤。Groovy 還支持排除范圍纯趋,“0..<4” 表示 0、1、2吵冒、3纯命。還可以創(chuàng)建字符范圍:“a..e” 相當(dāng)于 a、b痹栖、c亿汞、d、e揪阿×莆遥“a..

def range = 0..4

2、集合

def coll = ["Groovy", "Java", "Ruby"]

3南捂、映射

def hash = [name:"Andy", "VPN-#":45]

(二)閉包Closure

閉包是可執(zhí)行的代碼塊吴裤。它們不需要名稱,可以在定義之后執(zhí)行溺健。

1麦牺、 閉包的格式

def xxx = {paramters -> code}?//或者

def xxx = {無參數(shù),純code} 這種case不需要->符號

2鞭缭、 閉包的特點

閉包在Groovy中大量使用剖膳,比如很多類都定義了一些函數(shù),這些函數(shù)最后一個參數(shù)都是一個閉包岭辣。

Groovy中吱晒,當(dāng)函數(shù)的最后一個參數(shù)是閉包的話,可以省略圓括號易结。比如

其實標(biāo)識doLast為一個函數(shù)枕荞,函數(shù)的最后一個參數(shù)為閉包

doLast({

println'Hello world!'

})

有了圓括號,你會知道 doLast只是把一個Closure對象傳了進(jìn)去搞动。很明顯,它不代表這段腳本解析到doLast的時候就會調(diào)用println 'Hello world!' 渣刷。

但是把圓括號去掉后鹦肿,就感覺好像println 'Hello world!'立即就會被調(diào)用一樣!

舉例:閉包用于迭代

def acoll = ["Groovy", "Java", "Ruby"]

acoll.each{

println it

}

閉包中的it變量是一個關(guān)鍵字辅柴,指向被調(diào)用的外部集合的每個值 — 它是默認(rèn)值箩溃,可以用傳遞給閉包的參數(shù)覆蓋它。

(三)groovy腳本的實質(zhì)

既然是基于Java的碌嘀,Groovy會先把xxx.groovy中的內(nèi)容轉(zhuǎn)換成一個Java類涣旨。比如:

test.groovy的代碼是:

println?'Groovy world!'

Groovy把它轉(zhuǎn)換成這樣的Java類:

執(zhí)行groovyc-d classes test.groovy

groovyc是groovy的編譯命令,-d classes用于將編譯得到的class文件拷貝到classes文件夾下

二.Gradle

Gradle是一種依賴管理工具股冗,基于Groovy語言霹陡,面向Java應(yīng)用為主,它拋棄了基于XML的各種繁瑣配置,取而代之的是一種基于Groovy的內(nèi)部領(lǐng)域特定(DSL)語言烹棉。 用于自動化構(gòu)建攒霹、測試、發(fā)布打包浆洗。

(一)基本組件

Gradle是一個框架催束,它定義一套自己的游戲規(guī)則。我們要玩轉(zhuǎn)Gradle伏社,必須要遵守它設(shè)計的規(guī)則抠刺。下面我們來講講Gradle的基本組件:

Gradle中,每一個待編譯的工程都叫一個Project摘昌。每一個Project在構(gòu)建的時候都包含一系列的Task速妖。比如一個Android APK的編譯可能包含:Java源碼編譯Task、資源編譯Task第焰、JNI編譯Task买优、lint檢查Task、打包生成APK的Task挺举、簽名Task等杀赢。

1. gradle projects查看工程信息

到目前為止,我們了解了Gradle什么呢湘纵?

每一個Project都必須設(shè)置一個build.gradle文件脂崔。至于其內(nèi)容,我們留到后面再說梧喷。

對于multi-projects build砌左,需要在根目錄下也放一個build.gradle,和一個settings.gradle铺敌。

一個Project是由若干tasks來組成的汇歹,當(dāng)gradlexxx的時候,實際上是要求gradle執(zhí)行xxx任務(wù)偿凭。這個任務(wù)就能完成具體的工作产弹。

2. gradle tasks查看任務(wù)信息

gradleproject-path:tasks就行。注意弯囊,project-path是目錄名痰哨,后面必須跟冒號。

對于Multi-project匾嘱,在根目錄中斤斧,需要指定你想看哪個poject的任務(wù)。不過你要是已經(jīng)cd到某個Project的目錄了霎烙,則不需指定Project-path撬讽。

(二)gradle build的生命周期

Gradle有一個初始化流程蕊连,這個時候settings.gradle會執(zhí)行。

在配置階段锐秦,每個Project都會被解析咪奖,其內(nèi)部的任務(wù)也會被添加到一個有向圖里,用于解決執(zhí)行過程中的依賴關(guān)系酱床。

然后才是執(zhí)行階段羊赵。你在gradle xxx中指定什么任務(wù),gradle就會將這個xxx任務(wù)鏈上的所有任務(wù)全部按依賴順序執(zhí)行一遍扇谣!

(1)生命周期

eg:Single project build example

settings.gradle

println 'This is executed during the initialization phase.'

build.gradle

println 'This is executed during the configuration phase.'

task configured {

println 'This is also executed during the configuration phase.'

}

task test << {

println 'This is executed during the execution phase.'

}

task testBoth {

doFirst {

println 'This is executed first during the execution phase.'

}

doLast {

println 'This is executed last during the execution phase.'

}

println 'This is executed during the configuration phase as well.'

}

(2)setting.gradle中多工程配置

其中setting.gradle在多project的配置中昧捷,用于聲明包含的project及其層級關(guān)系(平坦和層級結(jié)構(gòu)的project都支持)

include 'project1', 'project2:child', 'project3:child1'

includeFlat 'project3', 'project4'

(3)根據(jù)生命周期定制task

eg:Logging of start and end of each task execution

build.gradle

task ok

task broken(dependsOn: ok) << {

thrownew RuntimeException('broken')

}

gradle.taskGraph.beforeTask { Task task ->

println "executing $task ..."

}

gradle.taskGraph.afterTask { Task task, TaskState state ->

if (state.failure) {

println "FAILED"

}

else {

println "done"

}

}

三.Gradle用途

(1)依賴管理

我們的project可能會用到其他的庫(本地、maven或者ivy)

eg:Declaring dependencies

本地project依賴

dependencies {

compile fileTree(include: ['*.jar'], dir: 'libs')

compile project(':bugrpt')

}

遠(yuǎn)程庫依賴

apply plugin: 'java'

repositories {

mavenCentral()

}

dependencies {

compile group: 'org.hibernate', name: 'hibernate-core', version: '3.6.7.Final'

testCompile group: 'junit', name: 'junit', version: '4.+'

}

標(biāo)識project需要hibernate-core一起編譯罐寨,project test需要junit的編譯靡挥,另外一種寫法group:name:version

dependencies {

compile 'org.hibernate:hibernate-core:3.6.7.Final'

}

像這些外部的庫,gradle是通過repository來找到的

eg:Usage of a remote Maven repository

build.gradle

repositories {

maven {

url "http://repo.mycompany.com/maven2"

}

}

eg:Usage of a remote Maven repository

build.gradle

repositories {

maven {

url "http://repo.mycompany.com/maven2"

}

}

repositories {

maven {

url "http://repo.mycompany.com/maven2"

}

}repositories {

ivy {

// URL can refer to a local directory

url "../local-repo"

}

}

(2)版本發(fā)布

可以將自己的lib工程發(fā)布到maven、jcenter等倉庫供其他開發(fā)者使用

eg發(fā)布工程

uploadArchives {

repositories {

ivy {

credentials {

username "username"

password "pw"

}

url "http://repo.mycompany.com"

}

}

}

(3) 差異管理

比如app生成不同版本(免費鸯绿,收費)跋破,適配特殊機型,多渠道等需要發(fā)多個包瓶蝴,最終能編譯出的apk的數(shù)量是由productflavor與BuildType決定的毒返,BuildType默認(rèn)有debug和release兩種

eg:免費與收費設(shè)置不同包名

productFlavors {

pay {

applicationId "me.ghui.gradledemo.pay"

}

free {}

}

eg:buildTypes 對應(yīng)的不同版本

android {

buildTypes {

debug {

applicationIdSuffix ".debug"

}

jnidebug {

initWith(buildTypes.debug)

packageNameSuffix ".jnidebug"

jniDebuggable true

}

}

}

對于每一種buildTypes會創(chuàng)建相應(yīng)的ssemble任務(wù),比如debug會自動創(chuàng)建assembleDebug任務(wù)

創(chuàng)建一個新的的Build Types非常簡單舷手,只需要在buildTypes下面通過調(diào)用initWith或者使用閉包添加一個新的元素拧簸。下表是可以配置的屬性以及默認(rèn)值:

屬性明 debug版本默認(rèn)值release或其他版本默認(rèn)值

debuggable true false

jniDebuggable false false

renderscriptDebuggable false false

renderscriptOptimLevel 3 3

applicationIdSuffix null null

versionNameSuffix null null

signingConfig android.signingConfigs.debug null

zipAlignEnabled false true

minifyEnabled false false

proguardFile N/A (set only) N/A (set only)

proguardFiles N/A (set only) N/A (set only)

eg:多渠道打包

附錄 gradle腳本基礎(chǔ)

1 project和task

task表示構(gòu)建的一次原子操作,包括編譯類男窟、創(chuàng)建jar包盆赤、發(fā)布到repository、生成javadoc等歉眷,而project通常包含多個task

task hello {

doLast {

println 'Hello world!'

}

}

這個腳本定義了一個叫做hello的task牺六,并且添加了一個action,這個action實際上是由groovy語言編寫的閉包汗捡,更簡潔的寫法

task hello << {

println 'Hello world!'

}

> gradle -q hello

Hello world!

2 task依賴

project('projectA') {

task taskX(dependsOn: ':projectB:taskY') << {

println 'taskX'

}

}

project('projectB') {

task taskY << {

println 'taskY'

}

}

3 可以動態(tài)創(chuàng)建task兔乞,并通過api操作task

4.times { counter ->

task "task$counter" << {

println "I'm task number $counter"

}

}

task0.dependsOn task2, task3

4 task可以定義屬性

task myTask {

ext.myProperty = "myValue"

}

task printTaskProperties << {

println myTask.myProperty

}

5 設(shè)置默認(rèn)

defaultTasks 'clean', 'run'

task clean << {

println 'Default Cleaning!'

}

task run << {

println 'Default Running!'

}

task other << {

println "I'm not a default task!"

}

6 可以添加HOOK

task distribution << {

println "We build the zip with version=$version"

}

task release(dependsOn: 'distribution') << {

println 'We release now'

}

gradle.taskGraph.whenReady {taskGraph ->

if (taskGraph.hasTask(release)) {

version = '1.0'

} else {

version = '1.0-SNAPSHOT'

}

}

7 定位task

1)使用task的名字

println hello.name

2)使用tasks collection

println tasks.hello.name

3)使用project:task路徑定位

tasks.getByPath(':projectA:hello').path

8 配置task

Configuring a task - with closure

task copy(type: Copy) {

description 'Copies the resource directory to the target directory.'

from 'resources'

into 'target'

include('**/*.txt', '**/*.xml', '**/*.properties')

}


網(wǎng)易云捕-網(wǎng)易旗下最專業(yè)的APP質(zhì)量跟蹤平臺

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市凉唐,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌霍骄,老刑警劉巖台囱,帶你破解...
    沈念sama閱讀 219,188評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異读整,居然都是意外死亡簿训,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,464評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來强品,“玉大人膘侮,你說我怎么就攤上這事〉拈唬” “怎么了琼了?”我有些...
    開封第一講書人閱讀 165,562評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長夫晌。 經(jīng)常有香客問我雕薪,道長,這世上最難降的妖魔是什么晓淀? 我笑而不...
    開封第一講書人閱讀 58,893評論 1 295
  • 正文 為了忘掉前任所袁,我火速辦了婚禮,結(jié)果婚禮上凶掰,老公的妹妹穿的比我還像新娘燥爷。我一直安慰自己,他們只是感情好懦窘,可當(dāng)我...
    茶點故事閱讀 67,917評論 6 392
  • 文/花漫 我一把揭開白布前翎。 她就那樣靜靜地躺著,像睡著了一般奶赠。 火紅的嫁衣襯著肌膚如雪鱼填。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,708評論 1 305
  • 那天毅戈,我揣著相機與錄音苹丸,去河邊找鬼。 笑死苇经,一個胖子當(dāng)著我的面吹牛赘理,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播扇单,決...
    沈念sama閱讀 40,430評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼商模,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了蜘澜?” 一聲冷哼從身側(cè)響起施流,我...
    開封第一講書人閱讀 39,342評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎鄙信,沒想到半個月后瞪醋,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,801評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡装诡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,976評論 3 337
  • 正文 我和宋清朗相戀三年银受,在試婚紗的時候發(fā)現(xiàn)自己被綠了践盼。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,115評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡宾巍,死狀恐怖咕幻,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情顶霞,我是刑警寧澤肄程,帶...
    沈念sama閱讀 35,804評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站确丢,受9級特大地震影響绷耍,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜鲜侥,卻給世界環(huán)境...
    茶點故事閱讀 41,458評論 3 331
  • 文/蒙蒙 一褂始、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧描函,春花似錦崎苗、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,008評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至互墓,卻和暖如春必尼,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背篡撵。 一陣腳步聲響...
    開封第一講書人閱讀 33,135評論 1 272
  • 我被黑心中介騙來泰國打工判莉, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人育谬。 一個月前我還...
    沈念sama閱讀 48,365評論 3 373
  • 正文 我出身青樓券盅,卻偏偏與公主長得像,于是被迫代替她去往敵國和親膛檀。 傳聞我的和親對象是個殘疾皇子锰镀,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,055評論 2 355

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

  • 導(dǎo)語: 隨著技術(shù)的發(fā)展,不管是前端開發(fā)咖刃、服務(wù)端開發(fā)或者是移動端開發(fā)(移動也是前端的一個分支)中都會用到自動化構(gòu)建工...
    伊始雨深閱讀 3,030評論 0 4
  • Groovy :是一種動態(tài)語言泳炉。 1:這種語言比較有特點,它和 Java 一樣嚎杨,也運行于 Java 虛擬機中胡桃。簡單...
    PeytonWu閱讀 1,557評論 0 1
  • 原文鏈接 前言 網(wǎng)上關(guān)于Gradle的教程很多,但很多都是以“面”切入— 通過大量講解其用法及其API分類來闡述磕潮。...
    adison閱讀 2,768評論 7 67
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理翠胰,服務(wù)發(fā)現(xiàn),斷路器自脯,智...
    卡卡羅2017閱讀 134,665評論 18 139
  • 今天女兒放學(xué)回來之景,高興的拿出一個本子,悄悄的告訴我這是老師獎勵的膏潮!我問她為什么獎勵你本子锻狗?她說今天測試,她得了滿分...
    倆千金的媽閱讀 143評論 0 0