1 Groovy
Groovy 是沒有類型的 Java 代碼 ,文法更簡潔。形式有點類似腳本語言。被gradle用于建構腳本的語言
1.1 特殊類型
1、範圍
範圍 是一系列的值。
比如 “0..4” 表明包括 整數 0、1、2、3、4。Groovy 還支援排除範圍,“0..<4” 表示 0、1、2、3。還能夠建立字元範圍:“a..e” 相當于 a、b、c、d、e。“a..<e” 包括小于 e 的全部值。
def range = 0..4
2、集合
def coll = ["Groovy", "Java", "Ruby"]
3、映射
def hash = [name:"Andy", "VPN-#":45]
1.2 閉包Closure
閉包是可運作的代碼塊。
它們不須要名稱。能夠在定義之後運作。
1、 閉包的格式
- def xxx = {paramters -> code} //或者
- def xxx = {無參數,純code} 這樣的case不須要->符号
2、 閉包的特點
閉包在Groovy中大量使用,比方非常多類都定義了一些函數,這些函數最後一個參數都是一個閉包。
Groovy中。當函數的最後一個參數是閉包的話,能夠省略圓括号。比方

事實上辨別doLast為一個函數,函數的最後一個參數為閉包
- doLast({
- println'Hello world!'
- })
有了圓括号。你會知道 doLast僅僅是把一個Closure對象傳了進去。非常明顯。它不代表這段腳本解析到doLast的時候就會調用println 'Hello world!' 。
可是把圓括号去掉後。就感覺好像println 'Hello world!'馬上就會被調用一樣!
舉例:閉包用于疊代
def acoll = ["Groovy", "Java", "Ruby"]
acoll.each{
println it
}
閉包中的
it
變量是一個keyword,指向被調用的外部集合的每一個值 — 它是預設值,能夠用傳遞給閉包的參數覆寫它。
1.3 groovy腳本的實質
既然是基于Java的,Groovy會先把xxx.groovy中的内容轉換成一個Java類。比方:
test.groovy的代碼是:
- println 'Groovy world!'
Groovy把它轉換成這種Java類:
運作 groovyc-d classes test.groovy
groovyc是groovy的編譯指令,-d classes用于将編譯得到的class檔案複制到classes目錄下
2 Gradle
Gradle是一種依賴管理工具,基于Groovy語言。面向Java應用為主,它抛棄了基于XML的各種繁瑣配置,取而代之的是一種基于Groovy的内部領域特定(DSL)語言。
用于自己主動化建構、測試、公布打包。
2.1 基本元件
Gradle是一個架構。它定義一套自己的遊戲規則。我們要玩轉Gradle。必需要遵守它設計的規則。以下我們來講講Gradle的基本元件:
Gradle中,每個待編譯的project都叫一個Project。
每個Project在建構的時候都包括一系列的Task。
比方一個Android APK的編譯可能包括:Java源代碼編譯Task、資源編譯Task、JNI編譯Task、lint檢查Task、打包生成APK的Task、簽名Task等。
1. gradle projects檢視工程資訊
到眼下為止,我們了解了Gradle什麼呢?
l 每個Project都必須設定一個build.gradle檔案。至于其内容。我們留到後面再說。
l 對于multi-projects build。須要在根檔案夾下也放一個build.gradle,和一個settings.gradle。
l 一個Project是由若幹tasks來組成的,當gradlexxx的時候,實際上是要求gradle運作xxx任務。
這個任務就能完畢詳細的工作。
2. gradle tasks檢視任務資訊
gradleproject-path:tasks 即可。注意,project-path是檔案夾名。後面必須跟冒号。
對于Multi-project。在根檔案夾中,須要指定你想看哪個poject的任務。
隻是你要是已經cd到某個Project的檔案夾了,則不需指定Project-path。
2.2 gradle build的生命周期
- l Gradle有一個初始化流程,這個時候settings.gradle會運作。
- l 在配置階段,每一個Project都會被解析。其内部的任務也會被加入到一個有向圖裡,用于解決運作過程中的依賴關系。
- l 然後才是運作階段。你在gradle xxx中指定什麼任務。gradle就會将這個xxx任務鍊上的所有任務所有按依賴順序運作一遍!
(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中多project配置
當中setting.gradle在多project的配置中。用于聲明包括的project及其層級關系(平坦和層級結構的project都支援)
include 'project1', 'project2:child', 'project3:child1'
includeFlat 'project3', 'project4'
(3)依據生命周期定制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"
}
}
3 Gradle用途
(1)依賴管理
我們的project可能會用到其它的庫(本地、maven或者ivy)
eg:Declaring dependencies
本地project依賴
dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
compile project(':bugrpt')
}
遠端庫依賴
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.+'
}
辨別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 local Ivy directory
build.gradle
repositories {
ivy {
// URL can refer to a local directory
url "../local-repo"
}
}
(2)版本号公布
eg:公布project
uploadArchives {
repositories {
ivy {
credentials {
username "username"
password "pw"
}
url "http://repo.mycompany.com"
}
}
}
(3) 差異管理
比方app生成不同版本号(免費。收費)。适配特殊機型,多管道等須要發多個包。終于能編譯出的apk的數量是由productflavor與BuildType決定的,BuildType預設有debug和release兩種
eg:免費與收費設定不同包名
productFlavors {
pay {
applicationId "me.ghui.gradledemo.pay"
}
free {}
}
eg:buildTypes 相應的不同版本号
android {
buildTypes {
debug {
applicationIdSuffix ".debug"
}
jnidebug {
initWith(buildTypes.debug)
packageNameSuffix ".jnidebug"
jniDebuggable true
}
}
}
對于每一種buildTypes 會建立對應的ssemble<BuildTypeName>任務,比方debug會自己主動建立assembleDebug任務
eg:多管道打包
4 gradle wrapper
gradlew通過包裹了gradle,然後通過配置中url下載下傳。存儲到使用者檔案夾
$USER_HOME/.gradle/wrapper/dists
.
啟動圖形界面
gradle --gui
附錄 gradle腳本基礎
1 project和task
task表示建構的一次原子操作,包括編譯類、建立jar包、公布到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 能夠動态建立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 設定預設
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')
}