一篇文章認識Gradle的使命

談談爲何要寫這樣一篇博客

Gradle對於咱們大多數Android開發者能夠說是熟悉又陌生。但這個理由並不足以讓我有動力寫下這篇文章,其主要由於是這樣的:最近參與項目開發,發現項目工程裏的的build.gradle比以前接觸的的複雜了許多,雖然大部份內容經過表面英文也勉強能看懂,但仍是有些內容會讓人懵逼。尤爲是gradle出錯的時候,我第一時間會運用一個很是熟練的技能,ctrl+c問題,ctrl+v到google,而後經過google出來的結果跟着改,運氣不錯喲,這麼簡單的改動就gradle經過了,這時喜悅以前噴涌而出,嘴角開始瘋狂的上揚。但其實心裏是很虛的,由於你根本不知道是基於什麼原理去解決的。因此總的來講本篇博客的目的就是兩個:html

  1. 減小無效的ctrl+c/v時間
  2. 弄懂gradle的使命,遇到gradle問題再也不那麼虛

本篇博客的核心內容分三點:java

  • Groovy和Java
  • Gradle的生命週期
  • task的定義

Groovy和Java

在學習gradle的過程當中最好記住下面一句話,避免在gradle的摩天大樓中迷失了方向android

Gradle腳本是基於Groovy語音的,於是它必定要遵循Groovy的語法git

Groovy是一門腳本語言,也是一門JVM語言,它最終是要編譯成class文件而後在jvm上執行,因此Java語言的特性Groovy都支持,咱們徹底能夠混寫Java和Groovy。咦,怎麼這段話好像在介紹kotlin見過呀!是的,若是你學過kotlin你會發現,kotlin和groovy的不少語法規則都同樣。github

既然如此,那Groovy的優點是什麼呢?簡單來講:Groovy提供了更加靈活簡單的語法,大量的語法糖以及閉包特性可讓你用更少的代碼來實現和Java一樣的功能。好比解析xml文件,Groovy就很是方便,只須要幾行代碼就能搞定,用Java則須要幾十行代碼。api

下面只簡單的介紹Groovy的幾個語法,更多的語法能夠參考官方文檔,本文的重點再也不這裏。bash

1. 字符串模版

def name = "world"
println "Hi ${name}"
複製代碼

2. def 關鍵字來聲明變量和函數

def a = 1 //省略了分號
def b = "hello world"
def int c = 1 

def hello(msg) {  //參數類型可省略
   println (msg) 
   1  //方法返回值可省略return
}
複製代碼
  • 在Groovy中,類型是弱化的,全部的類型均可以動態推斷
  • 在Groovy中不少東西均可以省略,好比語句後的分號,返回值最後的renturn,函數參數的類型

3. 閉包(Closure)

簡單的理解,經過一對{}把代碼塊框起來,做爲一個總體對象來處理數據結構

{
    [closureParameters ->] 
    sataments
}
複製代碼

[]內容是能夠省略的,但不表明沒有,Groovy自動幫我嗎分析推斷,從而省去人工書寫的繁瑣過程閉包

舉幾個栗子jvm

{ -> item++ }   //引用一個變量item

{ it -> println it } //使用隱含閉包參數it

{ println it }      //省略隱含閉包參數it

{ name -> println name } //顯示閉包參數

{ string x, int y ->    //多個閉包參數
    printIn "hey ${x} the value is $(y}" } 複製代碼

4. 運算符重載

Groovy中的很多運算符會被映射爲針對對象的常規函數調用。譬如:

a + b 會被Groovy 解釋爲 a.plus (b)
a - b 會被Groovy解釋爲 a.minus(b)
a[b] = c 會被Groovy解釋爲 a.putAt(b, c)
複製代碼

正由於有了這樣的特性,纔有了咱們常見的task語句:

task helloworId << 
{
    println 'hello, world } 複製代碼

Gradle的生命週期

gradle完成它的自動化編譯使命,須要通過三個過程,也就是它的生命週期

gradle life

1. 初始化

初始化的階段主要職責是定位有哪些須要處理的build文件。若是是單個工程,就會識別出單獨的build文件做爲下一個階段的輸入。若是是多工程,就會找到多個build文件,把它們做爲下一階段的輸入。這個階段settings.gradle文件會被解析。

2. 配置

處理全部的模塊的build腳本,處理依賴,屬性等。對於Android來講每一個模塊的build.gradle文件會被解析並配置,這個時候會構建整個task的鏈表(僅僅指存在依賴關係的task的集合,不是數據結構的鏈表)。這一階段的目標產物其實是由一個個task組成的DAG圖(Directed Acyclic Graph)

3. 執行

這個階段是真正體現Gradle價值的一個階段,他會根據上一階段的DAG結果來執行某一個特定的task,這個task所依賴的其餘task都將會被提早執行

下面有一個栗子能夠直觀的感覺到這個週期過程,傳送門:

全面理解Gradle - 執行時序

Task定義

Task能夠理解爲Gradle的執行單元。Gradle就是經過一個個task來完成具體的構建任務,下面咱們就來看看Task的定義。

task myTask {
    println "config myTask"
}
複製代碼

執行task: gradle myTask 或者 gradle clean

config myTask

能夠看出,只要我執行任何一個task,都會輸出config myTask。這是爲何呢?

由於每一個task執行以前都須要進行一遍完整的配置。

但不少時候咱們都不須要寫配置代碼,那還這麼作不是很影響執行速度?

這個時候能夠經過gradle的提供的一些API方法:

  • doFirst:task執行最開始的操做
  • doLast:task執行最後的操做,等價於leftShift操做,因此也能夠寫成這個操做符 <<

那麼把配置代碼和執行代碼分開來能夠寫成這樣:

task myTask {
    println "config myTask"
}

myTask << {
    println "after execute myTask"
}

myTask.doFirst {
    println "before execute myTask"
}

複製代碼

固然。不少時候在定義task的時候能夠繼承Gradle自己提供的Task,好比Copy、Delete、Sync等。

舉個栗子,繼承Delete的task

task clean(type: Delete) {
    delete rootProject.buildDir
}
複製代碼

用於刪除整個project根目錄下的build文件夾

小結

筆者分享的這篇內容並非要讓你掌握Gradle的某個具體知識點,畢竟Gradle的水仍是很深的,

  • Gradle腳本是基於Groovy語言的,於是它必定要遵循Groovy的語法
  • Gradle經過三個生命週期完成它的自動化編譯使命
  • Gradle經過執行單元Task完成具體的編譯工做

要想深刻的學習Gradle,仍是要須要看官方文檔的

相關文章
相關標籤/搜索