前言
又要開啟一個新系列了,這個系列我們來學習Gradle,它是一個基於JVM的新一代構建工具,關於Gradle完全可以寫一本書,這個系列會針對Android開發來對Gradle的知識進行精簡講解。Gradle目前已經應用於多個Android開發的技術體系中,比如構建系統、外掛化、熱修復和元件化等等,如果你不瞭解Gradle,那麼你對於上述技術體系的瞭解會大打折扣。為了讓大家能夠更好的學習Gradle,這篇文章不會介紹Gradle具體的技術細節,而是先介紹為什麼現在要用Gradle?
1.專案自動化
Gradle是一個構建工具,那麼為什麼要用構建工具,這就需要先從專案自動化開始講起。
在我們開發軟體時,會面臨相似的情況就是,我們需要去用IDE來進行編碼,當完成一些功能時會進行編譯、單元測試、打包等工作,這些工作都需要開發人員手動來實現。而一般的軟體都是迭代式開發的,一個版本接著一本版本,每個版本又可能有很多的功能,如果開發每次實現功能時都需要手動的進行編譯、單元測試和打包等工作,那顯然會非常耗時而且也容易出現問題,因此專案自動化應運而生,它有以下優點:
- 它可以儘量防止開發手動介入從而節省了開發的時間並減少錯誤的發生。
- 自動化可以自定義有序的步驟來完成程式碼的編譯、測試和打包等工作,讓重複的步驟變得簡單。
- IDE可能受到不同作業系統的限制,而自動化構建是不會依賴於特定的作業系統和IDE的,具有平臺無關性。
2.構建工具
構建工具用於實現專案自動化,是一種可程式設計的工具,你可以用程式碼來控制構建流程最終生成可交付的軟體。構建工具可以幫助你建立一個重複的、可靠的、無需手動介入的、不依賴於特定作業系統和IDE的構建。這麼說可能有些抽象,這裡拿APK的構建過程來舉例。
2.1 APK的構建過程
APK的構建過程可以根據官方提供的流程圖如下圖所示。
這個APK構建的過程主要分為以下幾步:
- 通過AAPT(Android Asset Packaging Tool)打包res資原始檔,比如AndroidManifest.xml、xml佈局檔案等,並將這些xml檔案編譯為二進位制,其中assets和raw資料夾的檔案不會被編譯為二進位制,最終會生成R.java和resources.arsc檔案。
- AIDL工具會將所有的aidl介面轉化為對應的Java介面。
- 所有的Java程式碼,包括R.java和Java介面都會被Java編譯器編譯成.class檔案。
- Dex工具會將上一步生成的.class檔案、第三庫和其他.class檔案編譯成.dex檔案。
- 上一步編譯生成的.dex檔案、編譯過的資源、無需編譯的資源(如圖片等)會被ApkBuilder工具打包成APK檔案。
- 使用Debug Keystore或者Release Keystore對上一步生成的APK檔案進行簽名。
- 如果是對APK正式簽名,還需要使用zipalign工具對APK進行對齊操作,這樣應用執行時會減少記憶體的開銷。
從以上步驟可以看出,APK的構建過程是比較繁瑣的,而且這個構建過程又是時常重複的,如果沒有構建工具,手動去完成構建工作,無疑對於開發人員是個折磨,也會產生諸多的問題,導致專案開發週期變長。
在Gradle出現之前,有三個基於Java的構建工具:Ant、Gant和Maven,它們被應用於Java或者Android開發中,我們來看看它們都有什麼特點。
2.2 Apache Ant
Ant在這裡不是螞蟻的意思(雖然它的圖示是螞蟻),而是Another Neat Tool的意思。
它是由 James Duncan Davidson 開發的(Tomcat 最初的開發者),最初是用來構建 Tomcat。在2000年,Ant成為一個獨立的專案並被髮布出來。Ant 是由 Java 編寫的構建工具,它的核心程式碼是由Java編寫的,因此具有平臺無關性,構建指令碼是XML格式的(預設為bulid.xml),如果你熟悉XML,那麼Ant 就比較容易上手。
Ant構建指令碼的樣式如下所示。
bulid.xml
<?xml version="1.0" encoding="UTF-8"?>
<project name="test" default="hello">
<echo message="running build.xml which is equivalent to build.gant"/>
<property file="build.properties"/>
<target name="init" description="init target" >
<echo message="Executing init target"/>
</target>
<target name="hello" depends="init" description="say hello target">
<echo message="${echo.msg}"/>
</target>
</project>
複製程式碼
Ant的構建指令碼由三個基本元素組成:一個project(工程)、多個target(目標)和可用的task(任務)。
Apache Ant有以下缺點:
- Ant無法獲取執行時的資訊。
- XML作為構建指令碼的語言,如果構建邏輯複雜,那麼構建指令碼就會又長又難以維護。
- Ant需要配合Ivy(一種管理專案依賴工具),否則Ant很難管理依賴。
- Ant在如何組織專案結構方面沒有給出任何指導,這導致Ant雖然靈活性高,但這樣的靈活導致每個構建指令碼都是唯一的而且很難被理解。
2.3 Gant
Gant 是一個基於Ant 的構建工具,它在Ant的基礎上用Groovy寫的DSL(領域特定語言)。如果用Ant 實現構建,但是不喜歡用XML來編寫構建指令碼或者現有的XML構建指令碼很難維護和管理,那麼Gant 是一個不錯的選擇。
Gant構建檔案的樣式如下所示。
build.gant
Ant.echo(message : `running build.gant`)
Ant.property(file : `build.properties`)
def antProperty = Ant.project.properties
target(init : `init target`) {
echo(message : `Executing init target`)
}
target(hello : `say hello target`) {
depends(init)
echo(message : antProperty.`echo.msg`)
}
setDefaultTarget(hello)
複製程式碼
這個build.gant等同於此前Ant的bulid.xml。
2.4 Apache Maven
Maven於2004年釋出,它的目標是改進開發人員在使用Ant時面臨的一些問題。Maven最初是為了簡化Jakarta Turbine專案的構建,它經歷了Maven到Maven3的發展,Maven作為後來者, 繼承了Ant的專案構建功能, 同樣採用了XML作為構建指令碼的格式。Maven具有依賴管理和專案管理的功能,提供了中央倉庫,能幫助我們自動下載庫檔案。
Maven的構建指令碼的樣式如下所示。
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.mycompany.app</groupId>
<artifactId>my-app</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>Maven Quick Start Archetype</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
複製程式碼
Maven相比Ant的優點:
- Ant是過程式的,開發者需要顯示的指定每個目標,以及完成該目標鎖需要執行的任務。每一個專案,開發著都需要重新編寫這一過程,這樣會產生大量的重複。Maven是宣告式的,專案的構建過程和過程中的各個階段都由外掛實現,開發者只需要宣告專案的基本元素就可以了,這很大程度消除了重複。
- Ant本身是沒有依賴管理,需要配合Ivy來管理依賴,而Maven本身就提供了依賴管理。
- Maven 使用約定而不是配置,它為工程提供了合理的預設行為,專案會知道去哪個目錄尋找原始碼以及構建執行時有那些任務去執行,如果你的專案遵從預設值,那麼只需要寫幾行XML配置指令碼就可以了。而Ant是使用配置且沒有預設行為的。
Maven的缺點:
- Maven的提供了預設的結構和生命週期,這些可能不適合你的專案需求。
- 為Maven寫定製的擴充套件過於累贅。
- Maven的中央倉庫比較混亂,當無法從中央倉庫中得到需要的類庫時,我們可以手工下載複製到本地倉庫中,也可以建立組織內部的倉庫伺服器。
- 國內連線Maven的中央倉庫比較慢,需要連線國內的Maven映象倉庫。
- Maven缺乏文件,不便於使用和理解。
3.Gradle的特性
Gradle是一款基於JVM的專注於靈活性和效能的開源構建工具。
從上圖可以看出,Gradle結合Ant和Maven等構建工具的最佳特性。它有著約定優於配置的方法、強大的依賴管理,它的構建指令碼使用Groovy或Kotlin DSL編寫,是Android的官方構建工具。Gradle的構建指令碼的樣式如下所示。
build.gradle
apply plugin:`java`
group=`com.mycompany.app`
archivesBaseName=`my-app`
version=`1.0-SNAPSHOT`
repositories{
mavenCentral()
}
dependencies{
testCompile `junit:4.11`
}
複製程式碼
這個build.gradlet等同於此前Maven的pom.xml。可以看出Groovy編寫構建指令碼程式碼量更少,可讀性更強。
下面列出Gradle與競爭對手不同的特性。
3.1 輕鬆的可擴充性
Gradle 有非常良好的擴充性。如果你想要在多個構建或者專案中分享可重用程式碼,Gradle的外掛會幫助你實現。將Gradle外掛應用於你的專案中,它會在你的專案構建過程中提供很多幫助:為你的新增專案的依賴的第三方庫、為你的專案新增有用的預設設定和約定(原始碼位置、單元測試程式碼位置)。其中Android Gradle外掛繼承Java Gradle外掛,在本系列後續的文章會介紹外掛的內容。
3.2 採用了Groovy
Ant和Maven的構建指令碼是由XML來編寫的,如果XML邏輯複雜內容太多就不容易維護。Gradle可以使用Groovy DSL來實現構建指令碼,Groovy 是基於Jvm一種動態語言,它的語法和Java非常相似併相容Java,因此你無需擔心學習Groovy的成本。Groovy在Java的基礎上增加了很多動態型別和靈活的特性,比起XML,Gradle更具有表達性和可讀性。
3.3 強大的依賴管理
Gradle提供了可配置的可靠的依賴管理方案。一旦依賴的庫被下載並儲存到本地快取中,我們的專案就可以使用了。依賴管理很好的實現了在不同的平臺和機器上產生相同的構建結果。
3.4 靈活的約定
Gradle可以為構建你的專案提供引導和預設值,如果你使用這種約定,你的Gradle構建指令碼不會有幾行。比起Ant,Gradle不僅僅提供了約定,還可以讓你輕鬆的打破約定。
3.5 Gradle Wrapper
Gradle Wrapper是對Gradle 的包裝,它的作用是簡化Gradle本身的下載、安裝和構建,比如它會在我們沒有安裝Gradle的情況下,去下載指定版本的Gradle並進行構建。Gradle的版本很多,所以有可能出現版本相容的問題,這時就需要Gradle Wrapper去統一Gradle的版本,避免開發團隊因為Gradle版本不一致而產生問題。
3.6 可以和其他構建工具整合
Gradle可以和Ant、Maven和Ivy進行整合,比如我們可以把Ant的構建指令碼匯入到Gradle的構建中。
3.7 底層API
Gradle顯然無法滿足所有企業級構建的所有要求,但是可以通過Hook Gradle的生命週期,來監控和配置構建指令碼。
3.8 社群的支援和推動
Gradle是一個開源的專案,它遵循了Apache License 2.0協議。Gradle的優良特性吸引了很多開發者並形成了Gradle社群,很多開源軟體開發者為Gradle的核心程式碼做出了共享。
4.總結
本篇文章從專案自動化開始講起,介紹了常用的構建工具:Ant、Gant和Maven,最後介紹了Gradle的特性,這些特性和其他競爭的構建工具相比有著很大的優勢和吸引力,這也是為什麼我們現在要用Gradle的原因。
感謝
《實戰Gradle》
《Android Gradle權威指南》
technologyconversations.com/2014/06/18/…
www.w3cschool.cn/gradle/6qo5…
blog.csdn.net/singwhatiwa…
www.w3cschool.cn/ant/
wiki.jikexueyuan.com/project/mav…
www.raychase.net/863
blog.csdn.net/coloriy/art…
這裡不僅分享Android、Java和移動前端相關技術,還有行業動態、技術資訊、面經和個人感悟。