Gradle技巧之語法淺談
回顧
在上一篇的博文(Gradle tip #2 : Tasks)中,我們討論了gradle構建的基本單位Task. 並且介紹了構建過程的各個階段及其生命週期.而本文會重點介紹gradle的語法.只有具備了gradle
的相關語法知識,才會大幅度的提高對於閱讀、學習或者編寫gradle指令碼的效率,正所謂”磨刀不誤砍柴工”是也.
引言
gradle 是groovy語言實現的構建工具. groovy是執行在jvm平臺的一門敏捷開發語言.其語法和java有諸多類似之處,然而其具備一些java沒有的概念需要讀者細細體會.下面會詳細的介紹
groovy的基本語法,當然如果您已經對groovy的語法有了一定的瞭解.可以直接跳過這一小節.
1、閉包的基本語法
閉包是groovy中最重要的概念之一. 簡單地說閉包(Closures)是一段程式碼塊. 這個程式碼塊可以接受引數並具有返回值. 有一點要非常注意的是, 閉包往往不是在需要使用的時候才寫出來
這麼一段程式碼(就像Java的匿名類那樣), 通過def 關鍵字可以宣告一個變數代表一個閉包,然後在需要的時候直接使用該變數即可,多說無益,請看如下的例子:
一個簡單的Hello World閉包:
def myClosure = { println 'Hello world!' } //execute our closure myClosure()
output: Hello world!
如下是一個接受引數的閉包的例子:
def myClosure = {String str -> println str } //execute our closure myClosure('Hello world!')
output: Hello world!
如果閉包只接受一個引數,這個引數在程式碼塊中可以用it代替:
def myClosure = {println it } //execute our closure myClosure('Hello world!')
output: Hello world!
如下是接受多個引數的閉包的例子:
def myClosure = {String str, int num -> println "$str : $num" } //execute our closure myClosure('my string', 21)
output: my string : 21
閉包裡面的引數型別可以省略不寫,例子如下:
def myClosure = {str, num -> println "$str : $num" } //execute our closure myClosure('my string', 21)
output: my string : 21
閉包還有一個比較酷的寫法就是,可以直接呼叫context裡面的變數,預設的context就是建立這個閉包的類(class) 例子如下:
def myVar = 'Hello World!' def myClosure = {println myVar} myClosure()
output: Hello world!
上面提到了閉包可以直接呼叫context的變數,這個context可以通過setDelegate()方法來改變,極大的增加了閉包的靈活性!
def myClosure = {println myVar} //I'm referencing myVar from MyClass class MyClass m = new MyClass() myClosure.setDelegate(m) myClosure() class MyClass { def myVar = 'Hello from MyClass!' }
output: Hello from MyClass!
2、閉包可以作為引數進行傳遞
在groovy中,將閉包作為引數傳遞進函式,是將邏輯進行分離解耦的重要手段.在上述的例子中,我們已經嘗試瞭如何將閉包作為引數進行傳遞.下面我們總結一下傳遞閉包的方法:
1 接受一個引數的函式
myMethod(myClosure)
2 如果函式只接受一個引數,括號可以忽略
myMethod myClosure
3 可以將閉包以插入語的形式建立
myMethod {println ‘Hello World’}
4 函式接受兩個引數
myMethod(arg1, myClosure)
5 接受兩個引數,同樣可以用插入語建立閉包
myMethod(arg1, { println ‘Hello World’ })
6 如果存在多個引數,且最後一個引數是閉包,閉包可以不寫在括號內
myMethod(arg1) { println ‘Hello World’ }
細心的朋友們是不是覺得上述的六種用法中,第三條和第六條很眼熟?很像gradle中的scripts了?
Gradle
在知道了groovy的基本語法(尤其是閉包)之後,下面我們就以一個簡單的gradle 指令碼作為例子具體感受一下:
buildscript { repositories { jcenter() } dependencies { classpath 'com.android.tools.build:gradle:1.2.3' } } allprojects { repositories { jcenter() } }
結合前文的例子,我們可以很容易的理解到,buildscript是一個接受閉包作為引數的函式,這個函式會在編譯的時候被gradle呼叫.這個函式的定義就類似於:def buildscript(Closure closure). 而allprojects 同理也是一個接受閉包作為引數的函式.
那麼問題來了,這些函式具體會在什麼時候被gradle呼叫呢?要回答這個問題就需要介紹另一個知識點:Project
Project
在這裡,我覺得逐句翻譯作者查閱文件的步驟沒有太大的意義,我自己總結了一下作者的概念如下:
理解gradle配置檔案中的script如何呼叫的關鍵就是理解project的相關概念.在gradle執行某個”任務”的時候,會按照各個task的依賴關係來依次執行. 而執行這些task的物件就是Project.說的在通俗一些,project就是你希望gradle為你做的事情,而要完成這些事情,需要將事情分成步驟一步一步的做,這些步驟就是task.
Script blocks
通過前文的學習,我們已經很清楚的瞭解到scipt block就是一段接受閉包的函式,這些函式會被Project呼叫,預設的情況下,gradle 已經準備
好了很多script用於我們對專案進行配置,例如buildScript{} … … 當然你也可以自己寫出符合規範的task來在編譯的過程中被呼叫.
下面我們先看一下Android Studio中預設的script:
apply plugin: 'com.android.application' android { compileSdkVersion 22 buildToolsVersion "22.0.1" defaultConfig { applicationId "com.trickyandroid.testapp" minSdkVersion 16 targetSdkVersion 22 versionCode 1 versionName "1.0" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } }
按照我們已經有的知識,上面的指令碼說明有一個名稱為android的函式,該函式接收閉包作為引數,然而其實在Gradle的文件中是不存在這個函式的. 那麼android指令碼怎麼會出現在這裡呢? 答案就是最上面的apply plugin:‘com.android.application’.這個外掛提供了android構建所需要的各種script.
既然gradle官方的文件中沒有android相關的script資訊,那我們該怎麼查閱呢? 您可以去官方的android網站上查閱,如果懶得找的話請點選這個連結:https://developer.android.com/shareables/sdk-tools/android-gradle-plugin-dsl.zip
您下載了前文連線的文件後,可以發現有一個html格式的文件的名字是AppExtension, 這個文件主要就是介紹了Android configuration blocks. 即在gradle官方文件中沒有的關於Android 配置的各種gradle script都可以在這裡進行查閱(幾個例子):
1、 compileSdkVersion 在文件中的描述是Required. Compile SDK version. 即這個指令碼是gradle進行Android構建之必需,並且這個指令碼是用來描述編譯的時候使用的sdk版本.
2、buildToolsVersion在文件中的描述是Required. Version of the build tools to use. 即該指令碼是構建之必需,其用於告訴gradle使用
哪個版本的build tools
3 … … (詳細情況請參閱文件吧)
Exercise
有了前文的學習作為基礎,我們已經瞭解了gradle語法以及android 外掛的指令碼查閱方法. 那麼接下來我們實際運用這些知識,自定義的對我們的Android專案進行一些配置. 在上述的AppExtension文件中,我查閱到了一個指令碼的名字是testOptions. 這段指令碼代表的是TestOption class呼叫,TestOption class裡有三個屬性:reportDir、resultsDir 和unitTests. 而reportDir就是測試報告最後儲存的位置,我們現在就來改一下這個地方.
android { ...... testOptions { reportDir "$rootDir/test_reports" } }
在這裡,我使用了”$rootDir/test_reports”作為測試結果的儲存位置, $root 指向的就是專案的根目錄.現在如果我通過命令列執行
./gradlew connectedCheck. gradle就會進行一系列的測試程式並且將測試報告儲存在專案根目錄下的test_reports檔案中.
注意一點的是,這個關於測試的小例子,別用在你真是的生產環境中,儘量保持你專案結構的”清潔”
相關文章
- 淺談Kotlin語法篇之基礎語法(一)Kotlin
- 淺談Kotlin語法篇之變數和常量(二)Kotlin變數
- 淺談Kotlin語法篇之Lambda表示式完全解析(六)Kotlin
- 淺談Kotlin語法篇之擴充套件函式(五)Kotlin套件函式
- 淺談Kotlin語法篇之如何讓函式更好地呼叫(三)Kotlin函式
- 淺談Oracle 主外來鍵刪除語法格式Oracle
- 淺談Kotlin語法篇之頂層函式、中綴呼叫、解構宣告(四)Kotlin函式
- 二、淺談 JSON 處理技巧JSON
- 小白路程之----淺談ES6部分語法
- 淺談Kotlin語法篇之lambda編譯成位元組碼過程完全解析(七)Kotlin編譯
- 淺談摩爾投票法
- 淺談倍增法求解LCA
- Gradle 之語言基礎 GroovyGradle
- 淺談HTTP之URLHTTP
- 淺談OpenGL之DSA
- 淺談JS詞法環境JS
- Gradle 使用技巧(一)Gradle
- Gradle入門系列(二)——groovy高階語法Gradle
- Gradle入門系列(一)——groovy基礎語法Gradle
- Gradle學習之三Groovy高階語法Gradle
- 淺談Nginx之反向代理Nginx
- C++語法小技巧C++
- 淺談高匿代理ip的檢測技巧
- Gradle 技巧與問題Gradle
- Java基礎之淺談介面Java
- Java基礎之淺談集合Java
- 淺談Node.js中ES6匯入語法的使用方法Node.js
- 談談ES6語法(彙總上篇)
- 談談ES6語法(彙總下篇)
- 談談ES6語法(彙總中篇)
- Gradle系列之Gradle外掛Gradle
- 淺談C語言中函式的使用C語言函式
- 淺談WPF之屬性系統
- 淺談WPF之MVVM工具包MVVM
- 淺談java之設計模式(1)Java設計模式
- Java基礎之淺談泛型Java泛型
- 梧桐資料庫淺談查詢最佳化技巧資料庫
- Dart語法篇之基礎語法(一)Dart
- 淺淺談ReduxRedux