Android專案中如何運用好Gradle?
摘要:本文作者賈吉鑫為大眾點評Android工程師,在進行團隊並行開發時,分庫遇到的問題很多都要通過Gradle指令碼解決。Gradle雖為構建神器,但學習曲線比較陡峭,要想在Android專案中用好Gradle必須要做到三點。
最近在忙團隊並行開發的事情,主要是將各個團隊的程式碼分庫,一方面可以降低耦合,為後面模組外掛化做鋪墊,另一方面採用二進位制編譯,可以加快編譯速度。分庫遇到了一些問題,很多都要通過Gradle指令碼解決,所以稍微花時間研究了一下。
Gradle雖為構建神器,但感覺學習曲線比較陡峭。Gradle User Guide內容很多,但有點太多了,多的你看不完,Gradle Plugin User Guide一篇文章主要講了Android相關的配置,看完可能感覺馬馬虎虎會用,但到了修改一些構建流程的時候還是不知所措。經過一段時間的摸索,我覺得在Android專案中用好Gradle,你要做到以下三點:
- 瞭解Groovy基本語法。
- 粗讀Gradle User Guide和Gradle Plugin User Guide。
- 實戰,實戰,再實戰。(三遍,你懂的)
涉及到的知識點和內容比較多,我不會一一講解,本文主要會解答自己學習過程中的一些疑問,講解一些相關概念和實戰經驗,過程中也會推薦一些有質量的部落格文章。
Groovy語言
Gradle基於Groovy語言,雖然接觸Gradle比較久,甚至寫過一點Groovy語句,但對語言本身並不瞭解。為什麼用Groovy呢?Groovy執行在JVM上,在Java語言的基礎上,借鑑了指令碼語言的諸多特性,相比Java程式碼量更少,Groovy相容Java,可以使用Groovy和Java混合程式設計,可以直接使用各種Java類庫。
Groovy語法的學習,推薦官方文章Differences with Java和IBM developerWorks的精通Groovy。瞭解了基本語法,對讀寫gradle指令碼都會有幫助,比如隨便舉下面幾個例子:
- 比如為何在gradle指令碼中使用InputStream不用import包,而使用ZipFile需要import包?因為groovy預設import了下面的包和類,無需再import.
java.io.* java.lang.* java.math.BigDecimal java.math.BigInteger java.net.* java.util.* groovy.lang.* groovy.util.*
- 經常看到${var1}的用法是怎麼回事? 這是Groovy中的GString,可以在雙引號中直接使用,用於字串疊加非常方便。
def dx = tasks.findByName("dex${variant.name.capitalize()}")
- 下面的程式碼你真的能看懂嗎?
//apply是一個方法,plugin是引數,值為'com.android.application' apply plugin: 'com.android.application' /** *buildscript,repositories和dependencies本身是方法名。 *後面跟的大括號部分,都是一個閉包,作為方法的引數。 *閉包可以簡單的理解為一個程式碼塊或方法指標。 */ buildscript { repositories { jcenter() } dependencies { classpath 'com.android.tools.build:gradle:1.2.3' } } //groovy遍歷的一種寫法 each後面是閉包 android.applicationVariants.each { variant -> }
Gradle概念
下面講幾個Gradle相關的概念,幾個比較重要的吧,更多的東西還是要自己去看Gradle User Guide。
生命週期
Gradle構建系統有自己的生命週期,初始化、配置和執行三個階段。
- 初始化階段,會去讀取根工程中setting.gradle中的include資訊,決定有哪幾個工程加入構建,建立project例項,比如下面有三個工程:include ‘:app’, ‘:lib1′, ‘:lib2′
- 配置階段,會去執行所有工程的build.gradle指令碼,配置project物件,一個物件由多個任務組成,此階段也會去建立、配置task及相關資訊。
- 執行階段,根據gradle命令傳遞過來的task名稱,執行相關依賴任務。
任務建立
很多文章都會告訴你,任務建立要這樣:
task hello { doLast { println "hello" } }
或者用<<替換doLast,那我就很納悶,定義個任務怎麼這麼麻煩,還要加什麼doLast,我直接這樣不行嗎?
task hello { println "hello" }
上面的這種寫法,“hello” 是在gradle的配置階段列印出來的,而前面的寫法是在gradle的執行階段列印出來的,所以怎麼寫要看你的需求了。
另外task中有一個action list,task執行時會順序執行action list中的action,doLast或者doFirst後面跟的閉包就是一個action,doLast是把action插入到list的最後面,而doFirst是把action插入到list的最前面。
任務依賴
當我們在Android工程中執行./gradlew build的時候,會有很多工執行,因為build任務依賴了很多工,要先執行依賴任務才能執行當前任務。任務依賴主要使用dependsOn方法,如下所示:
task A << {println 'Hello from A'} task B << {println 'Hello from B'} task C << {println 'Hello from C'} B.dependsOn A C.dependsOn B
瞭解更多,可以看一下偵躍翻譯的Gradle tip #3-Task順序。
增量構建
你在執行gradle命令的時候,是不是經常看到有些任務後面跟著[UP-TO-DATE],這是怎麼回事?
在Gradle中,每一個task都有inputs和outputs,如果在執行一個Task時,如果它的輸入和輸出與前一次執行時沒有發生變化,那麼Gradle便會認為該Task是最新的,因此Gradle將不予執行,這就是增量構建的概念。
一個task的inputs和outputs可以是一個或多個檔案,可以是資料夾,還可以是project的某個property,甚至可以是某個閉包所定義的條件。自定義task預設每次執行,但通過指定inputs和outputs,可以達到增量構建的效果。
依賴傳遞
Gradle預設支援傳遞性依賴,比如當前工程依賴包A,包A依賴包B,那麼當前工程會自動依賴包B。同時,Gradle支援排除和關閉依賴性傳遞。
之前引入遠端AAR,一般會這樣寫:
compile 'com.somepackage:LIBRARY_NAME:1.0.0@aar'
上面的寫法會關閉依賴性傳遞,所以有時候可能就會出問題,為什麼呢?本來以為@aar是指定下載的格式,但其實不然,遠端倉庫檔案下載格式應該是由pom檔案中packaging屬性決定的,@符號的真正作用是Artifact only notation,也就是隻下載檔案本身,不下載依賴,相當於變相的關閉了依賴傳遞,可以看一下sf的這個問題,通過新增transitive=true可以解決。但其實如果遠端倉庫有pom檔案存在,compile後面根本不需要加”@aar”,也就不會遇到這個問題了。
相關文章
- Android專案中如何用好構建神器Gradle?AndroidGradle
- 如何運用好夜間旅遊專案的地域文化元素
- SSH的櫃架中如何才能運用好設計模式呢!設計模式
- 在gradle中構建java專案GradleJava
- 使用Gradle檢視Android專案中庫的依賴關係GradleAndroid
- 如何在maven專案或者gradle專案中搭建swagger-本地測試工具MavenGradleSwagger
- Android專案中獨立Git專案分庫後的編譯除錯時Gradle的配置AndroidGit編譯除錯Gradle
- 專案實戰之gradle在實際專案中的使用Gradle
- 如何在 Android 專案中應用 OpenCV?AndroidOpenCV
- Gradle for Android 系列:初識 Gradle 檔案GradleAndroid
- gradle專案打包jarGradleJAR
- 專案中的運籌帷幄
- 從零開始的Android新專案(2):Gradle 篇AndroidGradle
- Android中gradle檔案中implementation和compile的異同AndroidGradleCompile
- maven 專案轉化成 gradle 專案實踐MavenGradle
- Gradle之多專案構建Gradle
- 專案構建工具 GradleGradle
- Gradle建立多模組專案Gradle
- Gradle動態配置專案Gradle
- Gradle for Android系列之二 build.gradle檔案GradleAndroidUI
- 多個專案多個 Gradle,如何一手管理Gradle
- 解決Android Studio每次匯入專案都會下載Gradle和Android Gradle plugin的問題AndroidGradlePlugin
- 如何在Android Gradle中新增原生so檔案依賴AndroidGradle
- [Gradle中文教程系列]-跟我學Gradle-8.2-多模組專案- 專案結構Gradle
- 【Java】【Gradle】Gradle構建SpringBoot專案,Gradle模組化管理JavaGradleSpring Boot
- 使用IDEA建立gradle專案IdeaGradle
- idea gradle 專案依賴IdeaGradle
- gradle手工搭建java專案搭建GradleJava
- 使用Gradle構建Java專案GradleJava
- Gradle構建多模組專案Gradle
- 如何用好短影片運營工具,打造實體店魅力
- 商業綜合體如何運用好場景主題空間
- Gradle For Android(四)Gradle 編譯中神祕的混淆GradleAndroid編譯
- Android通過Gradle釋出開源專案到binary/JcenterAndroidGradle
- 深入淺出Android Gradle構建系統(二:專案結構)AndroidGradle
- 深入淺出Android Gradle構建系統(2):專案結構AndroidGradle
- 像 npm 一樣在 Andriod 專案中引入 Gradle 依賴NPMGradle
- 如何提升專案的運營和管理?