關於Android Gradle你須要知道這些(1)

前言

作爲一個作Android的同窗,我想對於「Gradle」是再熟悉不過了,可是對於Gradle倒是有點陌生,幾個月前,只是停留在這樣簡單的使用上。android

compile 「com.strange.unfamiliar:1.0」
複製代碼

什麼讓我意識到其重要性呢?應該是在秋招完後,刷刷拉勾,看到杭州某創業公司對應屆Andoid 40k的誘惑,趕忙投了一波,投投投,而後收到了面試邀請,剛開始面,感受這不按套路出牌啊,並非很偏cs基礎,而是在工程實踐上,期間問到了gradle的問題,當時心裏OS程序員

勉強湊合了幾句以後,繼續追問,而後全程面試

面完以後要了面試官的聯繫方式,進行了一些溝通,意識到了其重要性,而後想着經過項目驅動來深刻的學習一波,決定擼QQ空間熱修復實現方式中打補丁包的Gradle插件,沒錯,就是要抄個nvwa。編程

so,準備出一系列文章來分享整個學習的過程。文章實際上是從去年已經開始寫了兩篇,而後持續delay了,這裏從新撿起來。本篇將對Gradle的一些功能,重要性和其一些基礎作下講解,接下來,將進行Android項目中Gradle的講解,如何在AndroidStudio中使用Gradle來進行一些自定義構建。接着來進行一個簡單的插件實現,最後着手來進行hotfix插件的實現,共分爲四個部分,但願在對本身的學習作一個總結的同時,可以讓零基礎入門的Gradle的可以跟隨博客對Gradle有個認識,同時可以實現一個簡單的Gradle插件。bash

Gradle是什麼?

Gradle是一個基於Apache AntApache Maven概念的項目自動化建構工具。它使用一種基於Groovy的特定領域語言來聲明項目設置,而不是傳統的XML。服務器

那麼Gradle相比於Ant 和 Maven的構建方式,有那些優點呢?閉包

  • 自動處理包相依關係 - 取自 Maven Repos 的概念
  • 自動處理佈署問題 - 取自 Ant 的概念
  • 條件判斷寫法直覺 - 使用 Groovy 語言

過去 Java 開發者經常使用 Maven 和 Ant 等工具進行封裝佈署的自動化,或是二者兼用,不過這兩個包彼此有優缺點,若是頻繁改變相依包版本,使用 Ant 至關麻煩,若是瑣碎工做不少,Maven 功能不足,並且二者都使用 XML 描述,至關不利於設計 if、switch 等判段式,即便寫了可讀性也不佳,而 Gradle 改良了過去 Maven、Ant 帶給開發者的問題,至今也成爲 Android Studio 內置的封裝佈署工具。app

Android中Gradle能夠作什麼?

上一篇文章中講到了一個Android項目的構建過程,Android 構建系統編譯應用資源和源代碼,而後將它們打包成可供您測試、部署、簽署和分發的 APK。Android Studio 使用 Gradle 這一高級構建工具包來自動化執行和管理構建流程,同時也容許您定義靈活的自定義構建配置。每一個構建配置都可自行定義一組代碼和資源,同時對全部應用版本共有的部分加以重複利用。Android Plugin for Gradle 與這個構建工具包協做,共同提供專用於構建和測試 Android 應用的流程和可配置設置。函數式編程

Gradle 和 Android 插件獨立於 Android Studio 運行。這意味着,能夠在 Android Studio 內、使用計算機上的命令行工具或在未安裝 Android Studio 的計算機(例如持續性集成服務器)上構建 Android 應用。若是您不使用 Android Studio,能夠學習如何從命令行構建和運行您的應用。不管您是從命令行、在遠程計算機上仍是使用 Android Studio 構建項目,構建的輸出都相同。函數

Android項目結構圖

如上圖所示,在一個Project中,除了咱們項目自身的代碼和資源以外,會有多個與項目構建相關的.gradle文件,這些.Gradle文件用來對於咱們使用Gradle進行構建項目的整個過程當中來使用。

Gradle中,每個待編譯的工程都叫一個Project。每個Project在構建的時候都包含一系列的Task。好比一個Android APK的編譯可能包含:Java源碼編譯Task、資源編譯Task、JNI編譯Task、lint檢查Task、打包生成APK的Task、簽名Task等。

####Gradle工做流程

Gradle的工做流程以下圖所示,在每個工做流程的先後,咱們均可以進行一些hook操做,來知足本身的需求。

Gradle工做流程

Gradle工做包含三個階段:

  • 首先是初始化階段。對咱們前面的multi-project build而言,就是執行settings.gradle
  • Initiliazation phase的下一個階段是Configration階段。
  • Configration階段的目標是解析每一個project中的build.gradle。好比multi-project build例子中,解析每一個子目錄中的build.gradle。在這兩個階段之間,咱們能夠加一些定製化的Hook。這固然是經過API來添加的。
  • Configuration階段完了後,整個build的project以及內部的Task關係就肯定了。一個Project包含不少Task,每一個Task之間有依賴關係。Configuration會創建一個有向圖來描述Task之間的依賴關係。因此,咱們能夠添加一個HOOK,即當Task關係圖創建好後,執行一些操做。
  • 最後一個階段就是執行任務了。固然,任務執行完後,咱們還能夠加Hook。

簡言之,Gradle有一個初始化流程,這個時候settings.gradle會執行。 在配置階段,每一個Project都會被解析,其內部的任務也會被添加到一個有向圖裏,用於解決執行過程當中的依賴關係。而後纔是執行階段。你在gradle xxx中指定什麼任務,gradle就會將這個xxx任務鏈上的全部任務所有按依賴順序執行一遍!

Gradle主要有三種對象

這三種對象和三種不一樣的腳本文件對應,在gradle執行的時候,會將腳本轉換成對應的對象:

  • Gradle對象:當咱們執行gradle xxx或者什麼的時候,gradle會從默認的配置腳本中構造出一個Gradle對象。在整個執行過程當中,只有這麼一個對象。Gradle對象的數據類型就是Gradle。咱們通常不多去定製這個默認的配置腳本。
  • Project對象:每個build.gradle會轉換成一個Project對象。
  • Settings對象:顯然,每個settings.gradle都會轉換成一個Settings對象。

構建的生命週期,首先根據settings.gradle文件構建出一個Seetings對象,而後根據Seetings中的配置,建立Project對象,去找各個project下的build.gradle文件,根據文件內容來對project對象進行配置。

一個project中Task的數量,取決於其中應用的插架的數目多少,經過

apply plugin: 'com.android.library' 

複製代碼

一個Task包含若干Action。因此,Task有doFirst和doLast兩個函數,用於添加須要最早執行的Action和須要和須要最後執行的Action。Action就是一個閉包。對於原有的Task,咱們能夠在其執行以前或者執行以後,進行一系列的Hook操做,在其執行以前和執行以後,添加一些操做。

tasks.getByName("task"){  
   it.doLast{  
       println "do the task"
     }  
}  
複製代碼

Groovy概述

這裏將對Groovy語言進行一個簡單的介紹,經過簡單地語法上的介紹,能夠很好地看明白接下來對於構建過程當中一些簡單地Groovy語法。經過簡短的介紹,能夠很好地幫助咱們看懂Gradle中的一些配置信息。

Groovy是一種動態語言,基於Java並拓展了Java。 Java程序員能夠無縫切換到使用Groovy開發程序。Groovy讓寫Java程序變得像寫腳本同樣簡單。寫完就能夠執行,Groovy內部會將其編譯成Java class而後啓動虛擬機來執行。下圖是Groovy和Java代碼和JVM的關係圖。

Groovy和Java,JVM關係

語言概述

  • Groovy中支持動態類型,即定義變量的時候能夠不指定其類型。(def不是必須的,可是爲了代碼清晰,建議仍是使用def關鍵字)
def a = 5;
def b = "groovy"

複製代碼
  • 函數的定義,咱們也無需進行參數類型的聲明,同時也能夠不進行返回值類型的聲明,可是須要經過def字段來定義,函數的最後一行做爲返回值。
def function1(arg1, arg2) {
	arg1 + arg2
}

String function2(str1, str2) {
	return str1 + str2
}

複製代碼
  • 函數調用支持 參數名:參數值方式調用
apply plugin: 'com.android.library'

複製代碼

plugin:參數名,'com.android.library':參數值

  • 強大字符串支持功能
//單引號對應Java中字符串
str1 = 'this string'

//雙引號,可經過$進行相應的轉譯
x = 1
str2 = "This is $x"

//經過換行實現每一行的間距
str3 = '''begin line1 line2 end'''

複製代碼
  • 閉包

(英語:Closure),又稱詞法閉包(Lexical Closure)或函數閉包(function closures),是引用了自由變量的函數。這個被引用的自由變量將和這個函數一同存在,即便已經離開了創造它的環境也不例外。因此,有另外一種說法認爲閉包是由函數和與其相關的引用環境組合而成的實體。對於閉包的實現,從函數式編程的角度來看就爲了解決一個輸入對應一個輸出的問題。例如當咱們想實現一個加法,咱們必須經過傳遞兩個參數來實現,可是藉助於函數式編程,咱們能夠作到只傳遞一個參數。

function plusAny(first) {
   return function(second) {
        return first + second;
   }
}

var longLiveSeniorFunc = plusAny(1);

longLiveSeniorFunc(1); 

複製代碼
  • Closure結構定義
def xxx = {paramters -> code}  
def xxx = {無參數,純code} 

複製代碼

根據上述兩種結構,下面分別舉例

def closure = {
	String param ->
	println "This is $param"
}

複製代碼
def closure = {
	println 'This is closure'
}
複製代碼
  • 如何調用閉包
closure.call('Hello')
closure('Hello')
複製代碼

閉包隱含一個自身參數it

def closure = {
	println "This is $it"
}

複製代碼

當閉包做爲一個函數的參數時

def testClosure(Closure closure) {
	closure()
}

testClosure(
	println 'Test'
)

複製代碼

總結

本文圍繞Gradle是什麼,能夠作什麼,在Android中起到了什麼做用,而後是Gradle的工做流程,Gradle中使用語言Groovy的一個概述,幫助咱們瞭解如何更好的使用Gradle。

參考文章

深刻理解Android(一):Gradle詳解

相關文章
相關標籤/搜索