1. 程式人生 > >Gradle與專案構建

Gradle與專案構建

最近發現有好多朋友問和Gradle相關的東西,於是決定寫一系列部落格,簡單備用。

隨著專案的逐步擴大與Android市場上應用需求的多樣化,越來越多的應用需要整合眾多的三方庫與其它依賴,在Google推出的最新idea Android Studio中,引入Gradle用於專案構建工具,那麼構建工具有什麼優勢呢?

構建工具的主要優勢有以下幾點:

  • 便捷性(Portability)
  • 自動化(Automation)
  • 可重複性(Repeatability)

那麼構建工具有很多(PS:ANT),為什麼要選擇Gradle呢?

主要原因還是Google粑粑在Android Studio中選用Gradle作為idea的構建系統,事實上,Android Studio將整個應用的構建過程指派給了Gradle,當點選”執行”按鈕時,Android studio會在執行過程中設定Gradle並在後臺監控,通過學習Gradle相關知識,我們可以擴充套件該預設行為以構建能力更強且經過適當測試的Android應用。Gradle使得開發人員只需通過點選按鈕就可以自動構建和測試應用,針對依賴和變種的管理也更加方便。另外Gradle是一種用於編寫構建指令碼的緊湊且強大的構建語言。

說了這麼多,怎麼安裝Gradle呢?

在Android Studio中,專案構建過程中會執行gradlew指令碼,在沒有Gradle的情況下,從網路端下載。在命令臺上我們可以使用如下方式安裝獨立的Gradle。

最新版的Gradle要求JDK或者JRE版本在1.7以上,所以先執行Java -version檢視JDK版本,過低先更新,隨後使用包管理工具進行安裝,在類Unix系統上使用SDKMAN,命令是sdk install gradle 3.3,在MAC上使用HomeBrew,命令是brew install gradle,在Windows上使用Chocolatey,命令是choco install gradle。隨後並不需要其他的手動安裝。

Gradle任務簡介

對於Gradle而言,它的一個優勢就是可擴充套件域模型,這個模型的核心就是任務(PS:task),任務是一種Grale可以推斷出的自約束工作單元,任務的關鍵是任務所進行的操作,比如我們會新建一個任務用於編譯某些java原始檔,或者把一個檔案從A目錄複製到B目錄又或者只是列印Hello,任務可以單獨執行操作也可以宣告對其他任務的依賴,Gradle會確保所有的這些依賴都在執行並確保它們所有的依賴性等等,任務還可以定義輸入和輸出,它所讀取及所寫入的檔案,這使得Gradle能確定任務是否需要執行自己的工作或者所有的內容是否是最新狀態,在這種情況下,它不需要執行。

建立簡單任務

使用gradle -V命令檢視Gradle版本,截圖如下:

這裡寫圖片描述

隨後我們編寫一個build.gradle檔案,內容如下:

task hello {
        doLast {
            println 'Hello world!'
        }
    }

在當前目錄執行gradle -q hello,我們可以看到如下執行結果:

這裡寫圖片描述

通過上述執行結果我們可以看出,在這裡這個指令碼只是簡單定義了一個名為hello的task,當執行gradle hello時,Gradle先執行名為hello的task,隨後執行task中的動作,在這個task中所進行的動作就是輸出Hello world!-q的意思是簡潔輸出,不輸出日誌,執行gradle hello的執行效果如下圖:

這裡寫圖片描述

Gradle需要執行大量工作才能啟動,這主要是因為它需要調起java虛擬機器例項,使用Gradle Demon可以縮短這一啟動時間,Gradle Demon是一種掛靠在作業系統後臺的程序,當Gradle使用Gradle Demon時,一個Gradle Demon已經啟動完成並長期運行於後臺,保證JBM例項處於活動狀態,隨後的Gradle都可以使用相同的例項執行,預設情況下,,當在命令列執行Gradle時,Android Studio會使用這種模式,但是必須明確指定啟用這種模式。

Gradle的前世

apply plugin: 'com.android.application'

android {
    compileSdkVersion 25
    buildToolsVersion "25.0.2"
    defaultConfig {
        applicationId "com.example.zbtuo.opengltriangles"
        minSdkVersion 15
        targetSdkVersion 25
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    compile 'com.android.support:appcompat-v7:25.1.0'
    testCompile 'junit:junit:4.12'
}

上面是一個build.gradle的完整檔案,從上述程式碼可以看出這是一種類似於分拆式JSON的語法.在最後可以看到一個名為hello的任務,用於輸出”Hello world!”,Gradle檔案是按照Gradle提供的特殊用途的構建語言編寫的,它基於一個叫Groovy的通用指令碼編制語言,Groovy對一些功能進行了語法改進使我們可以編寫語言比使用java等程式碼看起來更自然的構建指令碼。其次Groovy與Java完美整合,這是Gradle平臺使用的編寫語言,在使用Gradle時需要了解的主要內容是Android和task等關鍵字所來源於的Gradle構建語言,但是這對了解此構建語言如何以Groovy和Java為基礎很有幫助。整個構建指令碼具有所謂的委託物件,它會向構建指令碼內的Groovy指令碼編制語言公開Gradle構建語言。如果編寫了一個Gradle外掛,則可以用任何語言編寫它並使用相同的委託物件。Gradle構建語言也稱為Gradle DSL或域特定語言。域特定語言是針對特定任務精心定製的語言,在這個案例中,我們所談到的域是Android構建,請注意描述構建和提供有關,如何讓構建實現的說明之間存在巨大的差異。Gradle DSL宣告為使你僅負責描述構建而且Gradle本身知道如何使其實現,這意味著你的構建指令碼可能會短得多而且容易理解得多,但是在構建指令碼內有一個可由你處理的完全成熟且強大的程式語言。我們衷心建議你保持構建指令碼的宣告性並且儘量不要用低階邏輯汙染它,這正是Gradle外掛的用途,你可以採用Groovy,Java或Scala等任何JVM語言來編寫它們。