Learning Gradle

Android Studio作為Android應(yīng)用開發(fā)的官方IDE,默認使用Gradle作為構(gòu)建工具筹燕,所以對于Android應(yīng)用開發(fā)來說,Gradle是必須要掌握的工具。然而現(xiàn)實是舞丛,很多Android應(yīng)用開發(fā)人員都不太了解Gradle,并且網(wǎng)上大部分關(guān)于Android Gradle的資料都是幫助解決某個具體的配置問題果漾,缺乏系統(tǒng)深入的講解球切。本文就來系統(tǒng)且深入的學(xué)習Gradle

Java構(gòu)建工具的發(fā)展

Java構(gòu)建工具最早出現(xiàn)的是Ant绒障。Ant里的每一個任務(wù)(target)都可以互相依賴吨凑。Ant的最大缺點就是依賴的外部庫也要添加到版本控制系統(tǒng)中,因為Ant沒有一個機制來把這些外部庫文件放在一個中央庫里面户辱,結(jié)果就是不斷的拷貝和粘貼代碼鸵钝。

隨后Maven在2004年出現(xiàn)了,Maven引入了標準的項目和路徑結(jié)構(gòu)焕妙,還有依賴管理蒋伦,不幸的是自定義的邏輯很難實現(xiàn),唯一的方法就是引入插件焚鹊。

隨后Ant通過Apache Ivy引入依賴管理來跟上Maven的腳步痕届,Ant和Ivy集成實現(xiàn)了聲明式的依賴,比如項目的編譯和打包過程末患。

Gradle的出現(xiàn)滿足了很多現(xiàn)在構(gòu)建工具的需求研叫,Gradle提供了一個DSL(領(lǐng)域特定語言),一個約定優(yōu)于配置的方法璧针,還有更強大的依賴管理嚷炉,Gradle使得我們可以拋棄XML的繁瑣配置,引入動態(tài)語言Groovy來定義你的構(gòu)建邏輯探橱。

Why Gradle

Android Studio Project Site上對Android Studio為何選用Gradle作為構(gòu)建工具描述如下:

Gradle is an advanced build system as well as an advanced build toolkit allowing to create custom build logic through plugins. Here are some of its features that made us choose Gradle:

  • Domain Specific Language (DSL) based on Groovy, used to describe and manipulate the build logic
  • Build files are Groovy based and allow mixing of declarative elements through the DSL and using code to manipulate the DSL elements to provide custom logic.
  • Built-in dependency management through Maven and/or Ivy.
  • Very flexible. Allows using best practices but doesn’t force its own way of doing things.
  • Plugins can expose their own DSL and their own API for build files to use.
  • Good Tooling API allowing IDE integration.

DSL申屹,領(lǐng)域特定語言绘证,指不像通用目的語言那樣目標范圍涵蓋一切軟件問題,而是專門針對某一特定問題的計算機語言哗讥,如init.rc嚷那,renderscript等。

理解Groovy

由于Gradle是基于Groovy開發(fā)的杆煞,要深入理解Gradle魏宽,必須先了解Groovy。Groovy概括的說就是把寫Java程序變得像寫腳本一樣簡單决乎,寫完就可以執(zhí)行队询,Groovy內(nèi)部會將其編譯成Java字節(jié)碼,然后啟動虛擬機來執(zhí)行构诚。Groovy是用于Java虛擬機蚌斩,具有像PythonRubySmalltalk語言特性的敏捷的動態(tài)語言唤反,使用該種語言不必編寫過多的代碼凳寺,同時又具有閉包和動態(tài)語言中的其他特性。Groovy使用方式基本與Java代碼的使用方式相同彤侍,其設(shè)計時充分考慮了Java集成肠缨,這使Groovy與Java代碼的互操作很容易。

Groovy安裝

Mac上可以直接通過Homebrew安裝Groovy盏阶,具體命令如下:

$ brew install groovy

安裝完成后可通過如下命令查看:

$ groovy -v
Groovy Version: 2.4.8 JVM: 1.8.0_45 Vendor: Oracle Corporation OS: Mac OS X

Groovy基礎(chǔ)語法

  • 可以不同分號結(jié)尾晒奕。
  • 支持動態(tài)類型,即定義變量時可以不指定其類型名斟。
  • 可以使用關(guān)鍵字def定義變量和函數(shù)(Groovy推薦)(其實def會改變變量的作用域)脑慧。
  • Groovy中的所有事物都是對象。
def var = "Hello Groovy"
println var
println var.class

var = 5
println var
println var.class

輸出結(jié)果如下:

Hello Groovy
class java.lang.String
5
class java.lang.Integer
  • 單引號中的內(nèi)容嚴格對應(yīng)Java的String砰盐,不對$進行轉(zhuǎn)義闷袒。
  • 雙引號的內(nèi)容如果有$則會對$表達式先求值(GString)。
  • 三引號可以指示一個多行的字符串岩梳,并可以在其中自由的使用單引號和雙引號囊骤。
def name = 'Jerry'
println 'His name is $name'
println "His name is $name"

def members = """
    'Terry'
    "Larry" """
println "Team member is: " + members

輸出結(jié)果如下:

His name is $name
His name is Jerry
Team member is:
    'Terry'
    "Larry"
  • 函數(shù)定義時返回值和函數(shù)參數(shù)也可以不指定類型。
  • 未指定返回類型的函數(shù)定義必須使用def冀值。
  • 可以不使用return xxx來設(shè)置函數(shù)返回值也物,函數(shù)最后一行代碼的執(zhí)行結(jié)果被設(shè)置成返回值,如果定義時指明了類型則必須返回正確的數(shù)據(jù)類型列疗。
  • 函數(shù)調(diào)用可以不加括號她渴,構(gòu)造函數(shù)和無參函數(shù)除外应民。
def getValue(name) {// def is must
    name + "'s value is 10"
}
value = getValue "Terry"
println value

結(jié)果如下:

Terry's value is 10
  • Java原始數(shù)據(jù)類型在Groovy中為其對應(yīng)的包裝類型臂聋。
  • 類不支持default作用域,且默認作用域為public坤次,如果需要public修飾符,則不用寫它创葡。
  • 自動提供足夠使用的構(gòu)造函數(shù)(一個無參和帶一個Map參數(shù)的構(gòu)造函數(shù)浙踢,足夠)。
  • Groovy動態(tài)的為每一個字段都會自動生成getter和setter灿渴,并且我們可以通過像訪問字段本身一樣調(diào)用getter和setter。
  • Groovy所有的對象都有一個元類metaClass胰舆,我們可以通過metaClass屬性訪問該元類骚露。通過元類,可以為這個對象增加屬性和方法(在java中不可想象)缚窿!
  • 常用的集合類有List棘幸,MapRange倦零。
class Person {
    int id
    String name

    void setId(id) {
        println "setId($id)"
        this.id = id
    }

    String toString() {
        "id=$id, name=$name"
    }
}
merry = new Person()
merry.id = 1    // call merry.setId(1)
merry.setName "Merry"
println merry
println merry.getId().class
jerry = new Person(id: 2, name: "Jerry")
println jerry

運行結(jié)果如下:

setId(1)
id=1, name=Merry
class java.lang.Integer
setId(2)
id=2, name=Jerry

下面的例子展示通過metaClass向String對象中動態(tài)添加屬性和方法:

def msg = "Hello Groovy"
msg.metaClass.upper = { delegate.toUpperCase() }
msg.metaClass.lower = msg.toLowerCase()
println msg.upper()
println msg.lower

運行結(jié)果如下:

HELLO GROOVY
hello groovy

Groovy動態(tài)性

Groovy動態(tài)性示例如下:

class Dog {
    def bark() {
       println 'woof!'
    }
    def sit() {
       println 'sitting!'
    }
    def jump() {
       println 'boing!'
    }
}

def dog = new Dog()
def acts = ['sit','jump','bark']
acts.each {
    dog."${it}"()
}

運行結(jié)果如下:

sitting!
boing!
woof!

另一個動態(tài)性的例子:

class LightOn
{
    def doing()
    {
       println 'Ligth turning on...'
    }
}

class LightOff
{
    def doing()
    {
       println 'Ligth turning off...'
    }
}

class Switch
{
    def control(action)
    {
       action."doing"()
    }
}
def sh = new Switch()
sh.control(new LightOn())

運行結(jié)果如下:

Ligth turning on...

Groovy List

  • List變量由[]定義误续,其元素可以是任意對象,底層對應(yīng)Java的List接口扫茅。
  • 直接通過索引存取蹋嵌,而且不用擔心索引越界,當索引超過當前列表長度葫隙,List自動往該索引添加元素栽烂。
tmp = ["Jerry", 19 , true]
println "tmp[1] = " + tmp[1]
println tmp[5] == null
tmp[10] = 3.14
println "The size is " + tmp.size
println tmp

運行結(jié)果如下:

tmp[1] = 19
true
The size is 11
[Jerry, 19, true, null, null, null, null, null, null, null, 3.14]

Groovy Map

  • Map變量由[:]定義,冒號左邊是key恋脚,右邊是value腺办,key必須是字符串,value可以是任何對象糟描。另外key可以用引號包起來怀喉,也可以不用。
  • Map中元素的存取支持多種方法船响。
def score = "mark"
// id and name are treated as String
// "$score" is also correct
tmp = [id: 1, name: "Jerry", (score): 92]
println tmp
println "id: " + tmp.id
println "name: " + tmp["name"]
tmp.height = 183
println "height: " + tmp.height

運行結(jié)果如下:

[id:1, name:Jerry, mark:92]
id: 1
name: Jerry
height: 183

Groovy Range

  • Range是Groovy對List的擴展躬拢,由begin值 + .. + end值定義。
  • 不包含end值時使用<灿意。
tmp = 1..5
println tmp
println tmp.from
println tmp.to
tmpWithoutEnd = 1..<5
println tmpWithoutEnd.step(2)
println ""
println ""
println tmpWithoutEnd


tmp = 1.0f..5.0f
println tmp

運行結(jié)果如下:

[1, 2, 3, 4, 5]
1
5
[1, 3]


[1, 2, 3, 4]
[1.0, 2.0, 3.0, 4.0, 5.0]

Groovy文檔

  • Groovy的API文檔位于http://www.groovy-lang.org/api.html估灿。
  • 以Range為例,從getter方法我們知道Range有fromto屬性缤剧,盡管文檔中并沒有說明馅袁。
T   getFrom()
The lower value in the range.
T   getTo()
The upper value in the range.

Groovy閉包

  • 英文叫Closure,是Groovy中非常重要的一個數(shù)據(jù)類型或者說一種概念了荒辕。
  • 閉包汗销,是一種數(shù)據(jù)類型犹褒,它代表了一段可執(zhí)行代碼或方法指針。定義格式為:
    • def 閉包對象 = { parameters -> code }
    • def 閉包對象 = { code } // 參數(shù)個數(shù)少于2個時可以省略->符號
    • `def 閉包對象 = reference.&methodName
  • 閉包的調(diào)用方式:
    • 閉包對象.call(參數(shù))
    • 閉包對象(參數(shù))
  • 閉包只有一個參數(shù)時弛针,可省略書寫參數(shù)叠骑,在閉包內(nèi)使用it變量引用參數(shù)。
  • 閉包可以作為函數(shù)返回值削茁,函數(shù)參數(shù)宙枷,可以引用閉包外部定義的變量,可以實現(xiàn)接口方法茧跋。
def person = { id, name ->
    println "id=$id, name=$name"
}
person(1, "Jerry")
person.call(2, "Larry")
person 3, "Merry"

Closure resume = { "resume" }
println resume()

def hello = "Hello"
def length = hello.&length
println "The length is " + length()

def greeting = { "$hello, $it" }
// equals: greeting = { it -> "Hello, $it" }
println greeting('Groovy')

def exit = { -> "exit" }
// exit(1) <= wrong!!

def members = ["Jerry", "Larry", "Merry"]
members.each {
    println "Hello $it"
}

def welcome(name) {
    return {
        println "Welcome $name"
    }
}
println welcome("Terry")

運行結(jié)果如下:

id=1, name=Jerry
id=2, name=Larry
id=3, name=Merry
resume
The length is 5
Hello, Groovy
Hello Jerry
Hello Larry
Hello Merry
closure$_welcome_closure6@73a1e9a9

如何確定閉包的參數(shù)慰丛?查看API文檔。

Groovy DSL

  • Command Chain: 鏈式調(diào)用既可以省略圓括號瘾杭,又可以省略”.”號诅病。
  • 閉包作為函數(shù)調(diào)用的最后一個參數(shù)時,可以拿到圓括號外面粥烁。
// equivalent to: turn(left).then(right)
turn left then right

// equivalent to: take(2.pills).of(chloroquinine).after(6.hours)
take 2.pills of chloroquinine after 6.hours

// equivalent to: paint(wall).with(red, green).and(yellow)
paint wall with red, green and yellow

// with named parameters too
// equivalent to: check(that: margarita).tastes(good)
check that: margarita tastes good

// with closures as parameters
// equivalent to: given({}).when({}).then({})
given { } when { } then { }

一個例子:

def name(name) {
    println "name: $name"
    return this
}
def age(age) {
    println "age: $age"
    return this
}
def action(String tips, Closure c) {
    println "begin to $tips"
    c()
    println "end"
    return this
}

name "Jerry" age 18
// name("Jerry").age(18)

name "Herry"
age 22
action("eat") {
    println "eating..."
}

運行結(jié)果如下:

name: Jerry
age: 18
name: Herry
age: 22
begin to eat
eating...
end

Groovy腳本

Groovy腳本是什么贤笆?我們通過一個例子來看一下。

// variables.groovy

def x = 1 // or int x = 1

def printx() {
    println x
}

printx() // failed

運行結(jié)果如下:

Caught: groovy.lang.MissingPropertyException: No such property: x for class: variables
groovy.lang.MissingPropertyException: No such property: x for class: variables
    at variables.printx(variables.groovy:5)
    at variables.run(variables.groovy:8)

為何會出現(xiàn)找不到屬性x讨阻?我們來看看反編譯groovy運行時生成的.class文件芥永。使用如下命令在-d指定的目錄生成.class文件,然后使用JD-GUI查看:

groovyc –d classes variables.groovy
variables.class

可以看到:

  • XXX.groovy被轉(zhuǎn)換成XXX類变勇,它從Script類派生恤左。
  • 每一個腳本都會生成一個static main函數(shù)。這樣搀绣,當我們groovy XXX.groovy的時候飞袋,其實就是用調(diào)用虛擬機去執(zhí)行這個main函數(shù)。
  • 如果腳本定義了函數(shù)链患,則函數(shù)會被定義在XXX類中巧鸭。
  • 腳本中的其他代碼都會放到run函數(shù)中。

所以變量x是在是在run函數(shù)中定義的局部變量麻捻,當然無法在printx()函數(shù)的訪問纲仍。那要如何才能實現(xiàn)printx()函數(shù)訪問變量x呢?有兩種方式可以實現(xiàn)贸毕。
第一種方式:

x = 1 // replace def x = 1 or int x = 1

def printx() {
    println x
}

printx()

對應(yīng)的.class文件反編譯代碼:


另一種方式:

import groovy.transform.Field;

@Field x = 1 // <= def x = 1 or int x = 1

def printx() {
    println x
}

printx()

對應(yīng)的.class文件反編譯代碼:

Gradle介紹

Gradle被認為是Java世界構(gòu)建工具的一次飛躍郑叠,它提供:

  • 一個非常靈活通用的構(gòu)建工具。
  • 對多項目構(gòu)建提供強大支持明棍。
  • 強大的依賴管理機制乡革。
  • 完美支持已有的Maven和Ivy倉庫。
  • 支持依賴傳遞管理。
  • 腳本編寫基于Groovy沸版。
  • 豐富的描述構(gòu)建的領(lǐng)域模型嘁傀。

更多Gradle特性概述,可以訪問Gradle概述视粮。

Why Groovy

Gradle官方網(wǎng)站上對為何選用Groovy來開發(fā)的原因描述如下:

We think the advantages of an internal DSL (based on a dynamic language) over XML are tremendous when used in build scripts. There are a couple of dynamic languages out there. Why Groovy? The answer lies in the context Gradle is operating in. Although Gradle is a general purpose build tool at its core, its main focus are Java projects. In such projects the team members will be very familiar with Java. We think a build should be as transparent as possible to all team members.

In that case, you might argue why we don't just use Java as the language for build scripts. We think this is a valid question. It would have the highest transparency for your team and the lowest learning curve, but because of the limitations of Java, such a build language would not be as nice, expressive and powerful as it could be. [1] Languages like Python, Groovy or Ruby do a much better job here. We have chosen Groovy as it offers by far the greatest transparency for Java people. Its base syntax is the same as Java's as well as its type system, its package structure and other things. Groovy provides much more on top of that, but with the common foundation of Java.

For Java developers with Python or Ruby knowledge or the desire to learn them, the above arguments don't apply. The Gradle design is well-suited for creating another build script engine in JRuby or Jython. It just doesn't have the highest priority for us at the moment. We happily support any community effort to create additional build script engines.

Gradle基本概念

Gradle腳本是配置腳本细办,腳本執(zhí)行時會配置特定的對象,這些對象被稱為腳本的delegate對象蕾殴。腳本中可以使用delegate對象的屬性和方法笑撞。所有的Gradle腳本實現(xiàn)了org.gradle.api.Script接口,所以腳本中可以直接使用Script接口定義的屬性和方法区宇,Script接口中找不到的屬性或方法將被轉(zhuǎn)交給delegate對象娃殖。同時,Gradle腳本也是Groovy腳本议谷,同樣可以包含Groovy腳本允許的元素,方法堕虹、類定義等卧晓。

gradle-delegates

Gradle生命周期

Gradle執(zhí)行構(gòu)建時有它自己的生命周期,概括來說可以分為3個階段:
第一是初始化階段赴捞。初始化階段Gradle會創(chuàng)建一個Gradle對象逼裆、Settings對象和Root Project對象,然后在項目根目錄尋找并執(zhí)行settings.gradle文件來配置Settings對象赦政,并生成項目的Project樹胜宇。

第二是配置階段。配置階段Gradle會執(zhí)行特定的構(gòu)建腳本恢着,默認是各Project目錄下名為build.gradle的文件桐愉,以配置對應(yīng)的Project。配置階段結(jié)束時掰派,Gradle內(nèi)部會生成整個項目的有向無循環(huán)Task圖从诲。

第三是執(zhí)行階段。執(zhí)行階段Gradle依據(jù)命令行傳入的task名字在Task圖中找出此task的所有依賴鏈靡羡,并從各依賴鏈起點開始系洛,沿著依賴鏈依次執(zhí)行Task,最終得到編譯產(chǎn)物略步。

gradle-build-phasesM

Gradle用戶手冊中關(guān)于Gradle生命周期的描述如下:


gradle-lifecycle

Gradle生命周期的例子如下:

// settings.gradle
println 'This is executed during the initialization phase.'

// build.gradle in root directory
println 'This is executed during the configuration phase.'

task configured {
    println 'This is also executed during the configuration phase.'
}
task test {
    doLast {
        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.'
}

執(zhí)行結(jié)果如下:

This is executed during the initialization phase.
This is executed during the configuration phase.
This is also executed during the configuration phase.
This is executed during the configuration phase as well.

Gradle生命周期Hook

Gradle提供了豐富的Hook機制以獲知Gradle生命周期各個階段各類事件的發(fā)生描扯。常用的Hook可以通過Settings對象,ProjectTask對象來設(shè)置趟薄,設(shè)置方式包括配置閉包方式和設(shè)置監(jiān)聽器方式绽诚。

gradle-lifecycle-phases-hook

以項目評估結(jié)束事件為例說明:

// build.gradle in root directory
afterEvaluate {
    println "Project $name has been evaluated."
}

gradle.afterProject {
    println "Project $it.name is evaluated."
}

gradle.addProjectEvaluationListener(new ProjectEvaluationListener() {
    void afterEvaluate(Project project, ProjectState state) {
        println "Project $project.name was evaluated."
    }
    void beforeEvaluate(Project project) {
    }
})

執(zhí)行結(jié)果如下:

Project tutorial was evaluated.
Project tutorial is evaluated.
Project tutorial has been evaluated.

Gradle核心組件

Gradle的核心組件包括GradleSettingsProject憔购,Task宫峦,DependencyPlugin等玫鸟,每個核心組件都對應(yīng)很多有用的屬性导绷、方法和腳本塊。

Gradle組件

Gradle組件代表了一次Gradle構(gòu)建屎飘,通過Gradle組件能夠獲韧浊(或設(shè)置)本次構(gòu)建的一些全局信息,包括gradleVersion钦购,taskGraph檐盟,所有用到的plugins及添加各種Hook等。

Settings組件

Settings實例與settings.gradle文件存在一一對應(yīng)關(guān)系押桃,Gradle執(zhí)行時會使用settings.gradle來配置對應(yīng)的Settings實例葵萎。通常,在settings.gradle腳本中會通過include(String[])方法來添加對多項目的支持唱凯。Root Project會在Settings對象被創(chuàng)建時自動添加羡忘。另外,Settings組件還支持動態(tài)屬性磕昼,除了對象接口本身的屬性卷雕,還包含如下可用的屬性:

  • setting.gradle同級的gradle.properites文件定義的屬性。
  • 用戶Gradle目錄里gradle.properties定義的屬性票从。
  • 通過命令行-P參數(shù)定義的屬性漫雕。

示例如下:

// gradle.properties in project root directory
componentized=true

// settings.gradle
if (componentized) {
    include ':components'
}

執(zhí)行結(jié)果如下:

Project tutorial was evaluated.
Project tutorial is evaluated.
Project tutorial has been evaluated.
Project components was evaluated.
Project components is evaluated.

Project組件

Project組件是編譯腳本與Gradle交互的主API接口,通過Project接口能訪問Gradle所有功能峰鄙。Gradle運行時使用build.gradle配置對應(yīng)的project對象浸间。一個Project本質(zhì)上一些列Task的集合,每一個Task執(zhí)行一定的任務(wù)(類編譯先馆,生成javadoc等)发框。Project配置通常包括倉庫,依賴煤墙,產(chǎn)物梅惯,分組配置,插件的管理仿野。所有Project將都將被加入到Project層次樹中铣减,Project全路徑是其在層次樹中的唯一標識。Project配置還可以引入插件脚作,插件可以使得Project配置更加模塊化葫哗,并可重用缔刹。Project組件還支持5大范圍的動態(tài)屬性和5大范圍的動態(tài)方法。

5大范圍動態(tài)屬性


project-5-property-scopes

5大范圍動態(tài)方法


project-5-method-scopes

Ext屬性示例:

// build.gradle in root directory
ext {
    gradleVersion = "3.4"
    isSnapshot = true
}
ext.javaVersion = "1.7"

task addProperty(dependsOn: clean) {
    project.ext.prop3 = true
}
if (isSnapshot) {
    println "GradleVersion: $gradleVersion"
    println "JavaVersion: $javaVersion"
    println "Prop3: ${prop3}"
}

// build.gradle in components directory
println "GradleVersion in components: $gradleVersion"
println "JavaVersion in components: ${rootProject.ext.javaVersion}"

執(zhí)行結(jié)果如下:

GradleVersion: 3.4
JavaVersion: 1.7
Prop3: true
GradleVersion in components: 3.4
JavaVersion in components: 1.7

依賴管理

Gradle的依賴管理主要包括2大塊:

  • 解決依賴劣针。依賴指使得項目能夠正常編譯或運行的輸入組件校镐。
    • 依賴配置:包括項目內(nèi)依賴和外部依賴,并以配置分組捺典。
    • 倉庫配置:Gradle會在配置的倉庫地址查找外部依賴鸟廓。
  • 發(fā)布產(chǎn)物。產(chǎn)物指項目編譯生成的或需要上傳到中心的倉庫的輸出產(chǎn)物襟己。
    • 配置發(fā)布倉庫引谜。通常插件會定義好項目的產(chǎn)物,我們不必關(guān)心擎浴,但必須告訴Gradle將產(chǎn)物發(fā)布到何處员咽,MavenCentral,Ivy倉庫贮预,JCenter等贝室。

Gradle有6大類型依賴,如下圖仿吞,其中比較常用的包括External module dependency档玻,Project dependencyFile dependency茫藏。

dependency-types

依賴管理示例:

// In this section you declare where to find the dependencies of your project
repositories {
    jcenter()
    jcenter {
        url "http://jcenter.bintray.com/"
    }
    mavenCentral()
    maven {
        url "http://repo.company.com/maven2"
    }
    ivy {
        url "../local-repo"
    }
}

dependencies {
    compile 'com.google.guava:guava:20.0'
    compile project(':components')
    compile fileTree(dir: 'libs', include: '*.jar')
    testCompile group: 'junit', name: 'junit', version: '4.+'
}

Task組件

Gradle task represents some atomic piece of work which a build performs。Task可以使用task關(guān)鍵字定義霹琼,也可以使用TaskContainer.create()來定義务傲。一個Task可以依賴于另一個Task,Gradle支持使用must run aftershould run after直接控制2個Task的執(zhí)行順序枣申。預(yù)定義的Task可以被替換售葡。
另外Task還支持4大范圍動態(tài)屬性和通過Convention對象支持動態(tài)方法。

4大范圍動態(tài)屬性


task-4-property-scopes

Task使用示例:

// build.gradle in root project
task hello1 {
    doLast {
        println "Hello1 Task"
    }
}
task hello2 << {
    ext.prop2 = "prop2"
    println "Hello2 Task"
}
hello2.dependsOn hello1
task(hello3, dependsOn: hello2) {
    doFirst {
        println "Prop2: ${hello2.ext.prop2}"
        println "Hello3 Task"
    }
}
tasks.create('hello4').dependsOn('hello3')
hello4.doLast {
    println "Hello4 Task"
}

運行結(jié)果如下:

:hello1
Hello1 Task
:hello2
Hello2 Task
:hello3
Prop2: prop2
Hello3 Task
:hello4
Hello4 Task

Plugin組件

Gradle插件就是將很多可在多個不同項目或構(gòu)建中重用的編譯邏輯(屬性忠藤、方法和Task等)打包起來挟伙。可以使用不同的語言來實現(xiàn)插件模孩,如Groovy尖阔,Java,Scala榨咐,插件最終被編譯成字節(jié)碼介却。插件源碼可位于3類地方:

  • Build script:插件自動被編譯并被include到classpath中,build script外不可用块茁。
  • buildSrc project:buildSrc子項目自動被編譯并被include到classpath中齿坷,整個項目可用桂肌,其他項目不可用。
  • Standalone project:可以發(fā)布jar或發(fā)布到公共倉庫永淌,其他項目可用崎场。

Gradle Wrapper目錄結(jié)構(gòu)

Gradle Wrapper可以使得每個項目擁有各自的Gradle版本而不互相影響。當前項目中Gradle相關(guān)文件說明如下:

gradle-wrapper-in-project

用戶主目錄下Gradle相關(guān)文件說明如下:


gradle-wrapper-in-home

Android Plugin for Gradle

Android Plugin for Gradle就是通過Gradle插件機制方式實現(xiàn)Gradle在Android平臺的擴展遂蛀,詳細信息請參考Gradle Plugin User GuideAndroid Gradle DSL Reference谭跨。


參考

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市答恶,隨后出現(xiàn)的幾起案子饺蚊,更是在濱河造成了極大的恐慌,老刑警劉巖悬嗓,帶你破解...
    沈念sama閱讀 206,126評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件污呼,死亡現(xiàn)場離奇詭異,居然都是意外死亡包竹,警方通過查閱死者的電腦和手機燕酷,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來周瞎,“玉大人苗缩,你說我怎么就攤上這事∩睿” “怎么了酱讶?”我有些...
    開封第一講書人閱讀 152,445評論 0 341
  • 文/不壞的土叔 我叫張陵,是天一觀的道長彼乌。 經(jīng)常有香客問我泻肯,道長,這世上最難降的妖魔是什么慰照? 我笑而不...
    開封第一講書人閱讀 55,185評論 1 278
  • 正文 為了忘掉前任灶挟,我火速辦了婚禮,結(jié)果婚禮上毒租,老公的妹妹穿的比我還像新娘稚铣。我一直安慰自己,他們只是感情好墅垮,可當我...
    茶點故事閱讀 64,178評論 5 371
  • 文/花漫 我一把揭開白布惕医。 她就那樣靜靜地躺著,像睡著了一般噩斟。 火紅的嫁衣襯著肌膚如雪曹锨。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 48,970評論 1 284
  • 那天剃允,我揣著相機與錄音沛简,去河邊找鬼齐鲤。 笑死,一個胖子當著我的面吹牛椒楣,可吹牛的內(nèi)容都是我干的给郊。 我是一名探鬼主播,決...
    沈念sama閱讀 38,276評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼捧灰,長吁一口氣:“原來是場噩夢啊……” “哼淆九!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起毛俏,我...
    開封第一講書人閱讀 36,927評論 0 259
  • 序言:老撾萬榮一對情侶失蹤炭庙,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后煌寇,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體焕蹄,經(jīng)...
    沈念sama閱讀 43,400評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,883評論 2 323
  • 正文 我和宋清朗相戀三年阀溶,在試婚紗的時候發(fā)現(xiàn)自己被綠了腻脏。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 37,997評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡银锻,死狀恐怖永品,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情击纬,我是刑警寧澤鼎姐,帶...
    沈念sama閱讀 33,646評論 4 322
  • 正文 年R本政府宣布,位于F島的核電站更振,受9級特大地震影響症见,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜殃饿,卻給世界環(huán)境...
    茶點故事閱讀 39,213評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望芋肠。 院中可真熱鬧乎芳,春花似錦、人聲如沸帖池。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,204評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽睡汹。三九已至肴甸,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間囚巴,已是汗流浹背原在。 一陣腳步聲響...
    開封第一講書人閱讀 31,423評論 1 260
  • 我被黑心中介騙來泰國打工友扰, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人庶柿。 一個月前我還...
    沈念sama閱讀 45,423評論 2 352
  • 正文 我出身青樓村怪,卻偏偏與公主長得像,于是被迫代替她去往敵國和親浮庐。 傳聞我的和親對象是個殘疾皇子甚负,可洞房花燭夜當晚...
    茶點故事閱讀 42,722評論 2 345

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

  • 這篇文章講給大家?guī)韌radle打包系列中的高級用法-自己動手編寫gradle插件。我們平常在做安卓開發(fā)時审残,都會在...
    呆萌狗和求疵喵閱讀 15,974評論 22 80
  • 導(dǎo)語: 隨著技術(shù)的發(fā)展梭域,不管是前端開發(fā)、服務(wù)端開發(fā)或者是移動端開發(fā)(移動也是前端的一個分支)中都會用到自動化構(gòu)建工...
    伊始雨深閱讀 3,020評論 0 4
  • 本篇主要是個人學(xué)習gradle的筆記總結(jié) 一.開始之前 1. 為什么學(xué)習Gradle 采用DSL(Doma...
    zyq_neuq閱讀 1,487評論 2 12
  • Groovy :是一種動態(tài)語言搅轿。 1:這種語言比較有特點病涨,它和 Java 一樣,也運行于 Java 虛擬機中介时。簡單...
    PeytonWu閱讀 1,545評論 0 1
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理没宾,服務(wù)發(fā)現(xiàn),斷路器沸柔,智...
    卡卡羅2017閱讀 134,599評論 18 139