Android Gradle 滿滿乾貨分享

Gradle介紹

Gradle是一個基於JVM的新一代構建工具,能夠用於自動化自定義有序的步驟來完成代碼的編譯、測試和打包等工做,讓重複的步驟變得簡單,用於實現項目自動化,是一種可編程的工具,你能夠用代碼來控制構建流程最終生成可交付的軟件。構建工具能夠幫助你建立一個重複的、可靠的、無需手動介入的、不依賴於特定操做系統和IDE的構建java

Gradle優點

1.Gradle結合Ant和Maven等構建工具的最佳特性。它有着約定優於配置的方法、強大的依賴管理,它的構建腳本使用Groovy或Kotlin 編寫android

2.Gradle 有很是良好的拓展性。若是你想要在多個構建或者項目中分享可重用代碼,Gradle的插件會幫助你實現。將Gradle插件應用於你的項目中,它會在你的項目構建過程當中提供不少幫助:爲你的添加項目的依賴的第三方庫、爲你的項目添加有用的默認設置和約定(源代碼位置、單元測試代碼位置)。其中Android Gradle插件繼承Java Gradle插件面試

3.Gradle可使用Groovy來實現構建腳本,Groovy 是基於Jvm一種動態語言,它的語法和Java很是類似併兼容Java,所以你無需擔憂學習Groovy的成本。Groovy在Java的基礎上增長了不少動態類型和靈活的特性,比起XML,Gradle更具備表達性和可讀性。編程

4.Gradle提供了可配置的可靠的依賴管理方案。一旦依賴的庫被下載並存儲到本地緩存中,咱們的項目就可使用了。依賴管理很好的實現了在不一樣的平臺和機器上產生相同的構建結果。windows

5.Gradle能夠爲構建你的項目提供引導和默認值,若是你使用這種約定,你的Gradle構建腳本不會有幾行。數組

6.Gradle Wrapper是對Gradle 的包裝,它的做用是簡化Gradle自己的下載、安裝和構建,好比它會在咱們沒有安裝Gradle的狀況下,去下載指定版本的Gradle並進行構建。Gradle的版本不少,因此有可能出現版本兼容的問題,這時就須要Gradle Wrapper去統一Gradle的版本,避免開發團隊由於Gradle版本不一致而產生問題。緩存

7.Gradle能夠和Ant、Maven和Ivy進行集成,好比咱們能夠把Ant的構建腳本導入到Gradle的構建中性能優化

8.Gradle顯然沒法知足全部企業級構建的全部要求,可是能夠經過Hook Gradle的生命週期,來監控和配置構建腳本。服務器

9.社區的支持和推進閉包

想了解更多有關於Gradle知識的小夥伴,小編給準備了一期視頻專門講解Gradle:揭祕Android開發效率提高十倍的利器-Gradle 提取碼: 3m8g
更多資料分享歡迎Android工程師朋友們加入安卓開發技術進階互助:856328774免費提供安卓開發架構的資料(包括Fultter、高級UI、性能優化、架構師課程、 NDK、Kotlin、混合式開發(ReactNative+Weex)和一線互聯網公司關於Android面試的題目彙總。

gradle 入門

gradle這個基於Groovy的DSL,DSL(Domain Specifc Language)意爲領域特定語言,只用於某個特定的領域。咱們只要按照Groovy的DSL語法來寫,就能夠輕鬆構建項目

task:
task(任務)和action(動做)是Gradle的重要元素。task表明一個獨立的原子性操做,好比複製一個文件,編譯一次Java代碼,這裏咱們簡單的定義一個名爲hello的任務。doLast 表明task執行的最後一個action,通俗來說就是task執行完畢後會回調doLast中的代碼

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

也能夠寫成

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

操做符<< 是doLast方法的快捷版本

Gradle的任務
Gradle的任務,包括建立任務、任務依賴、 動態定義任務和任務的分組和描述
1 建立任務
1.1直接用任務名稱建立。

def Task hello=task(hello)
hello.doLast{
     println "hello world"
}

1.2任務名稱+任務配置建立

def Task hello=task(hello,group:BasePlugin.BUILD_GROUP)
hello.doLast{
     println "hello world"
}

1.3.TaskContainer的create方法建立。

tasks.create(name: 'hello') << {
    println "hello world"
}

1.4 經過上面dsl語法建立

任務依賴
任務依賴會決定任務運行的前後順序,被依賴的任務會在定義依賴的任務以前執行。建立任務間的依賴關係以下所示。

task hello << {
    println 'Hello world!'
}
task go(dependsOn: hello) << {
    println "go for it"
}

在hello任務的基礎上增長了一個名爲go的任務,經過dependsOn來指定依賴的任務爲hello,所以go任務運行在hello以後。
3 .動態定義任務
動態定義任務指的是在運行時來定義任務的名稱

3.times {number ->
    task "task$number" << {
        println "task $number"
    }
}

times是Groovy在java.lang.Number中拓展的方法,是一個定時器。3.times中循環建立了三個新任務,隱式變量number的值爲0,1,2,任務的名稱由task加上number的值組成,達到了動態定義任務的目的。

運行gradle -q task0構建腳本

任務的分組和描述
Gradle有任務組的概念,能夠爲任務配置分組和描述,以便於更好的管理任務,擁有良好的可讀性。

task hello {
    group = 'build'
    description = 'hello world'
    doLast {
        println "任務分組: ${group}"
        println "任務描述: ${description}"
    }
}
task go(dependsOn: hello) << {
    println "go for it"
}

Gradle日誌級別
級別  用於
ERROR   錯誤消息
QUIET     重要的信息消息
WARNING 警告消息
LIFECYCLE   進度信息消息
INFO    信息性消息
DEBUG   調試消息

前面咱們經過gradle -q +任務名稱來運行一個指定的task,這個q是命令行開關選項,經過開關選項能夠控制輸出的日誌級別。

開關選項    輸出日誌級別
無日誌選項   LIFECYCLE及更高級別
-q或者 --quiet    QUIET及更高級別
-i或者 --info INFO及更高級別
-d或者 --debug    DEBUG及更高級別

Gradle 命令行

Gradle 的語法
1.聲明變量
Groovy中用def關鍵字來定義變量,能夠不指定變量的類型,默認訪問修飾符是public。

def a = 1;
def int b = 1;
def c = "hello world";

2.方法
方法使用返回類型或def關鍵字定義,方法能夠接收任意數量的參數,這些參數能夠不申明類型,若是不提供可見性修飾符,則該方法爲public,若是指定了方法返回類型,能夠不須要def關鍵字來定義方法,若是不使用return ,方法的返回值爲最後一行代碼的執行結果。

用def關鍵字定義方法。

task method <<{
    add (1,2)
    minus 1,2 //1
}
def add(int a,int b) { 
 println a+b //3
}  
int minus(a,b) { 
  return a-b 
}

3.類
Groovy類很是相似於Java類。

task method <<{
    def p = new Person()
    p.increaseAge 5
    println p.age
}
class Person {                       
    String name                      
    Integer age =10
    def increaseAge(Integer years) { 
        this.age += years
    }
}

Groovy類與Java類有如下的區別:
默認類的修飾符爲public。
沒有可見性修飾符的字段會自動生成對應的setter和getter方法。
類不須要與它的源文件有相同的名稱,但仍是建議採用相同的名稱。

4.語句
(1) 斷言
Groovy斷言和Java斷言不一樣,它一直處於開啓狀態,是進行單元測試的首選方式。

task method <<{
  assert 1+2 == 6
}

(2)for循環
Groovy支持Java的for(int i=0;i<N;i++)和for(int i :array)形式的循環語句,另外還支持for in loop形式,支持遍歷範圍、列表、Map、數組和字符串等多種類型

//遍歷範圍
def x = 0
for ( i in 0..3 ) {
    x += i
}
assert x == 6
//遍歷列表
def x = 0
for ( i in [0, 1, 2, 3] ) {
    x += i
}
assert x == 6
//遍歷Map中的值
def map = ['a':1, 'b':2, 'c':3]
x = 0
for ( v in map.values() ) {
    x += v
}
assert x == 6

(3)switch語句

task method <<{
def x = 16
def result = ""

switch ( x ) {
    case "ok":
        result = "found ok"
    case [1, 2, 4, 'list']:
        result = "list"
        break
    case 10..19:
        result = "range"
        break
    case Integer:
        result = "integer"
        break
    default:
        result = "default"
}
assert result == "range"
}

5.數據類型
Groovy中的數據類型主要有如下幾種:

Java中的基本數據類型
Groovy中的容器類
閉包
(1)字符串
在Groovy種有兩種字符串類型,普通字符串String(java.lang.String)和插值字符串GString(groovy.lang.GString)

def name = 'Android進階之光'
println "hello ${name}"
println "hello $name"

task method <<{
def name = '''Android進階之光
       Android進階解密
Android進階?'''
println name 
}

(2)List
Groovy沒有定義本身的集合類,它在Java集合類的基礎上進行了加強和簡化。Groovy的List對應Java中的List接口,默認的實現類爲Java中的ArrayList。

def number = [1, 2, 3]         
assert number instanceof List  
def linkedList = [1, 2, 3] as LinkedList    
assert linkedList instanceof java.util.LinkedList

task method <<{
def number  = [1, 2, 3, 4]   
assert number [1] == 2
assert number [-1] == 4 //1  

number << 5     //2             
assert number [4] == 5
assert number [-1] == 5
}

def name = [one: '魏無羨', two: '楊影楓', three: '張無忌']   
assert name['one']  == '魏無羨' 
assert name.two  == '楊影楓'

註釋1處的索引-1是列表末尾的第一個元素。註釋2處使用<<運算符在列表末尾追加一個元素
其餘

String a = '23'
int b = a as int
def c = a.asType(Integer)
assert c instanceof java.lang.Integer

Gradle Files
咱們在AS中用到的Gradle其實應該被叫作 Android Gradle Plugin,也就是安卓項目上的gradle插件;

Gradle插件會有版本號,每一個版本號又對應有一個或一些 Gradle發行版本(通常是限定一個最低版本),也就是咱們常見的相似gradle-3.1-all.zip這種東西;
若是這兩個版本對應不上了,那你的工程構建的時候就會報錯。

Android Studio 3.0 以後自動將插件版本升級到3.0.0,因此咱們也須要對應地把Gradle升級到4.1才行

另外, Android Gradle Plugin又會跟 Android SDK BuildTool有關聯,由於它還承接着AndroidStudio裏的編譯相關的功能,這也是咱們要在項目的 local.properties 文件裏寫明Android SDK路徑、在build.gradle 裏註明 buildToolsVersion 的緣由。

因此 Android Gradle Plugin 本質上就是 一個AS的插件,它一邊調用 Gradle自己的代碼和批處理工具來構建項目,一邊調用Android SDK的編譯、打包功能,從而讓咱們可以順暢地在AS上進行開發。

最基礎的文件配置

在android studio中,沒有相似於 Eclipse 工做空間(Workspace)的概念,而是提出了Project和Module這兩個概念,Project是最頂級的結構單元,而後就是Module,一個Project能夠有多個Module。目前,主流的大型項目結構基本都是多Module的結構,這類項目通常是按功能劃分的。一個Project是由一個或多個Module組成,儘可能讓各模塊處於同一項目之中,此時彼此之間具備互相依賴的關聯關係,在通常狀況下,Android是默認單Project單Module的,這時Project和Module合二爲一,在沒有修改存儲路徑的時候,顯然Project對Module具備強約束做用。

咱們能夠簡單的理解爲:一個Project表明一個完整的APP,Module表示APP中的一些依賴庫或獨立開發的模塊。好比能夠新建一個library作爲module,而後在主APP上點右鍵 open module setting的Dependencies中添加一個模塊依賴。而後主APP中就可使用module中的類了

一個項目有一個setting.gradle、包括一個頂層的Project的 build.gradle文件、每一個Module 都有本身的一個build.gradle文件,android studio默認建立一個app的Module。

setting.gradle:這個 setting 文件定義了哪些module 應該被加入到編譯過程,對於單個module 的項目能夠不用須要這個文件,可是對於 multimodule 的項目咱們就須要這個文件,不然gradle 不知道要加載哪些項目。這個文件的代碼在初始化階段就會被執行。

頂層的project的build.gradle文件的配置最終會被應用到全部項目中。
buildscript:定義了 Android 編譯工具的類路徑。repositories中,jCenter是一個著名的 Maven 倉庫。

dependencies {
        classpath 'com.android.tools.build:gradle:3.1.0' 這裏配置gradle的插件來編譯gradle文件,同時也能夠配置其餘插件,gradle插件的版本須要與gradle-wrapper.properties中gradle版本對應
}

allprojects:中定義的屬性會被應用到全部 moudle 中,可是爲了保證每一個項目的獨立性,咱們通常不會在這裏面操做太多共有的東西。
apply plugin:第一行代碼應用了Android 程序的gradle插件,做爲Android 的應用程序,這一步是必須的,由於plugin中提供了Android 編譯、測試、打包等等的全部task。
每一個項目單獨的 build.gradle:針對每一個moudle 的配置,若是這裏的定義的選項和頂層build.gradle定義的相同,後者會被覆蓋。
android:這是編譯文件中最大的代碼塊,關於android 的全部特殊配置都在這裏,這就是又咱們前面的聲明的 plugin 提供的。
defaultConfig就是程序的默認配置,注意,若是在AndroidMainfest.xml裏面定義了與這裏相同的屬性,會以這裏的爲主。
這裏最有必要要說明的是applicationId的選項:在咱們曾經定義的AndroidManifest.xml中,那裏定義的包名有兩個用途:一個是做爲程序的惟一識別ID,防止在同一手機裝兩個同樣的程序;另外一個就是做爲咱們R資源類的包名。在之前咱們修改這個ID會致使全部用引用R資源類的地方都要修改。可是如今咱們若是修改applicationId只會修改當前程序的ID,而不會去修改源碼中資源文件的引用。
buildTypes:定義了編譯類型,針對每一個類型咱們能夠有不一樣的編譯配置,不一樣的編譯配置對應的有不一樣的編譯命令。默認的有debug、release 的類型。
能夠經過配置buildConfigField設置一些key-value對,這些key-value 對在不一樣編譯類型的 apk 下的值不一樣,好比咱們能夠爲debug 和release 兩種環境定義不一樣的服務器,還能夠經過manifestPlaceholders 修改manifest裏面meta-data的值

    buildTypes {
        debug {
            minifyEnabled false
            shrinkResources false
            manifestPlaceholders = [aaaa: "122222423524123139666"]
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
          buildConfigField("String","URL","http://www.baidu.com")

        }
        release {
            minifyEnabled true
            shrinkResources true
            signingConfig signingConfigs.release
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            manifestPlaceholders = [aaaa: "12222133655466889666"]
            buildConfigField("String","URL","http://www.google.com")
        }
    }

String host = BuildConfig.url;//這裏取buildConfigField的值

//manifest裏面配置
    <meta-data
            android:name="JPUSH_APPKEY"
            android:value="${aaaa}" />

dependencies:是屬於gradle 的依賴配置。它定義了當前項目須要依賴的其餘庫。

Gradle Wrapper
radle 不斷的在發展,新的版本不免會對以往的項目有一些向後兼容性的問題,這個時候,gradle wrapper就應運而生了。

gradlw wrapper 包含一些腳本文件和針對不一樣系統下面的運行文件。wrapper 有版本區分,可是並不須要你手動去下載,當你運行腳本的時候,若是本地沒有會自動下載對應版本文件。

在不一樣操做系統下面執行的腳本不一樣,在 Mac 系統下執行./gradlew …,在windows 下執行gradle.bat進行編譯。

若是你是直接從eclipse 中的項目轉換過來的,程序並不會自動建立wrapper腳本,咱們須要手動建立。在命令行輸入如下命令便可

gradle wrapper --gradle-version 2.4

它會建立以下目錄結構:

想了解更多有關於Gradle知識的小夥伴,小編給準備了一期視頻專門講解Gradle:揭祕Android開發效率提高十倍的利器-Gradle 提取碼: 3m8g
更多資料分享歡迎Android工程師朋友們加入安卓開發技術進階互助:856328774免費提供安卓開發架構的資料(包括Fultter、高級UI、性能優化、架構師課程、 NDK、Kotlin、混合式開發(ReactNative+Weex)和一線互聯網公司關於Android面試的題目彙總。
相關文章
相關標籤/搜索