Gradle系列(一):Groovy基礎
Gradle系列(二):AndroidStudio的Gradle簡介
Gradle系列(三):項目實踐
前言
關于Gradle的文章很多,但是大多是以一些技巧為主,東敲西打看了之后可能解決了一些問題,但對于新的需求,gradle如何運用到項目中還是一知半解。我準備稍微深層一點了解gradle,從基本語法開始到如何用到實際項目中,在此我把gradle的學習分成三個部分,分享給大家:
- 第一部分:Groovy基礎
- 第二部分:android studio中gradle插件簡介
- 第三部分:項目實踐
Groovy基礎
項目中build.gradle都是用groovy寫的,不了解一下groovy怎么能看得懂呢?這里只需要知道groovy的一些基礎知識,比如怎么定義變量,定義方法,方法怎么使用,閉包的使用,這些就差不多了。
首先要知道groovy是一種腳本語言,有下面三個特點:
- 是一種動態(tài)語言,不需要編譯直接生效
- 是一種DSL,即Domain Specific Language(專門領域的編程語言,所以比較難閱讀)
- Groovy基于Java同時也像是一種腳本語言(基于java,這個看下面基本語法就明白了)
基本語法
- ****定義基本變量:****
def variable1 = 1 //可以不使用分號結尾
def varable2 = "I am a person"
def int x = 1 //變量定義時,也可以直接指定類型
- ****字符串:****
1 單引號''中的內(nèi)容嚴格對應Java中的String,不對$符號進行轉義
def singleQuote='I am $ dolloar' //輸出就是I am $ dolloar
2 雙引號""的內(nèi)容則和腳本語言的處理有點像,如果字符中有$號的話,則它會$表達式先求值。
def doubleQuoteWithoutDollar = "I am one dollar" //輸出 I am one dollar
def x = 1
def doubleQuoteWithDollar = "I am $x dolloar" //輸出I am 1 dolloar
3 三個引號'''xxx'''中的字符串支持隨意換行 比如
def multieLines = ''' begin
line 1
line 2
end '''
- ****定義函數(shù):****
String testFunction(arg1,arg2){//無需指定參數(shù)類型
...
}
def nonReturnTypeFunc(){
last_line //最后一行代碼的執(zhí)行結果就是本函數(shù)的返回值
}
//如果指定了函數(shù)返回類型,則可不必加def關鍵字來定義函數(shù)
String getString(){
return "I am a string"
}
- ****函數(shù)調(diào)用:****
println("test") ---> println "test"http:// 可以不加括號,但是建議:自定義的方法調(diào)用加上括號! API提供的方法調(diào)用可以不用括號
****數(shù)據(jù)類型:****
** java中的基礎數(shù)據(jù)類型**
在Groovy中所有事物都是對象,int count = 12; //這里的count其實是Integer類型,其他的使用和Java一樣
- ****容器類****
1.List
變量定義:List變量由[]定義,也可以賦予一些初始值,比如
def aList = [5,'string',true] //List由[]定義,其元素可以是任何對象
變量存取:可以直接通過索引存取,而且不用擔心索引越界。如果索引超過當前鏈表長度,List會自動
往該索引添加元素
assert aList[1] == 'string'
assert aList[5] == null //第6個元素為空
aList[100] = 100 //設置第101個元素的值為10
assert aList[100] == 100
那么,aList到現(xiàn)在為止有多少個元素呢?
println aList.size ===>結果是101
2.Map
Map由[:]定義,注意其中的冒號。冒號左邊是key,右邊是Value。key必須是字符串,value可以是任何對象。另外,key可以用''或""包起來,也可以不用引號包起來。比如
def mapData = [:]
mapData.put("name","test name")
println(mapData.get("name"))//輸出“test name”
3.閉包(Closure)
- 定義:閉包,是一種數(shù)據(jù)類型,它代表了一段可執(zhí)行的代碼。他可以作為方法的參數(shù),或者返回值,也可以獨立運行
//自定義一個閉包
def aClosure = { //閉包是一段代碼,所以需要用花括號括起來..
String param -> println("test closure,para = $param") //這個箭頭很關鍵。箭頭前面是參數(shù)定義,箭頭后面是代碼
return 200 //返回值
}
//調(diào)用這個閉包:(用call方法或者直接蠶食寫在括號里面)
def count = aClosure.call("dml")
// def count2 = aClosure("dml")
println("$count")
在Gradle控制臺看一下輸出:
上面說到Closure也可以作為方法的參數(shù),在Android Gradle中有不少這樣的用法,比如:
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
debug{
applicationVariants.all { variant ->
variant.outputs.each { output ->
def outputFile = output.outputFile
if (outputFile != null && outputFile.name.endsWith('.apk')) {
// 輸出apk名稱為boohee_v1.0_2015-01-15_wandoujia.apk
def fileName = "boohee_v${defaultConfig.versionName}_${variant.productFlavors[0].name}.apk"
output.outputFile = new File(outputFile.parent, fileName)
}
}
}
}
}
分析一下這里代碼是什么意思:
這里debug的配置代碼:
作用是根據(jù)多渠道打包配置,重新命名APK(這里的實例代碼是在productFlavors中配置了“wandoujia”),這里不考慮這個配置,看下這段代碼用到了
applicationVariants.all和variant.outputs.each兩個Android Gradle插件API提供了兩個方法,第一個方法大致意思是獲取project對應的app,第二個方法大致意思是遍歷生成的所有debug和release的apk,并且重命名!
看下each這個方法,參數(shù)就是一個Closure,并且遍歷自己,把每一個item傳入這個自定義的Closure執(zhí)行,而在這個Closure中就是我們自己的實現(xiàn):傳入
output變量,對output重命名。Closure有點類似java的函數(shù)回調(diào)。
- 閉包使用注意:
1.如果一個方法的最后一個參數(shù)是Closure那么,可以不用圓括號,比如上面的all方法和each方法
2.如果閉包沒有定義參數(shù),那么它默認擁有參數(shù)it,類似于java的this:
def bClosure = {println("param = $it")
}
bClosure.call("this closure!") //輸出: param = this closure!
3.閉包的參數(shù)怎么傳
比如上面的
variant.outputs.each方法,雖然知道他要傳入closure參數(shù),但是這個closure參數(shù)傳幾個呢 ? 我們無法確定,只有通過API:
才能知道這個closure只接受一個參數(shù)!如果我們傳入多參數(shù)的closure這里會報錯,所以說closure和上下文有很強的關聯(lián)性,我們必須熟悉一些api才能很好地傳入closure!
-
IO操作
Groovy提供了簡單的讀取文件的方法,通過一個實例了解一下:
在我們公司項目中,一些基礎功能比如網(wǎng)絡模塊,通用控件等單獨編譯成aar文件,放到項目的根目錄lib文件夾。
我們可以利用gradle的IO操作讀取lib里面的file名稱:
//獲取基礎庫版本號
def path = rootProject.getRootDir().getAbsolutePath() + "/libs"
def configFile = new File(path)
def files = configFile.listFiles()
def aar1 = files[0].getName()
def aar2 = files[1].getName()
println(aar1 )
println(aar2 )
輸出:
那這個有什么用呢,后面第三部分的實踐會講到。
其他
Groovy還有一些技巧:
- 讀取xml文件,比如讀取manifest.xml文件信息
- 封裝獨立的工具類tools.gradle,比如獲取Android版本名稱,版本號,拷貝文件等IO操作
這些等用到的時候再說