爲了不被Diss,先聲明瞭,本文不算原創,只是對幾篇Gradle編譯提速的文章進行了: 搬運、整理、細化和補漏,文尾已列出相關的參考文獻!先上個圖舒服下:html
(PS:這是直接新建的項目經過各類折騰後編譯的時間,筆者公司的項目折騰完耗時5s左右, 可是由於兼容要改的東西多,升級gradle等操做並沒弄,不過也是效果明顯,真的能夠試試~)java
大部分的Android開發仔吐槽的最多的基本都是等Gradle編譯。android
編譯能夠說是平常操做最頻繁的,在調UI,調試改Bug時候達到一個峯值,每改點東西, 就build一下。能夠說是至關可怕,咱們來粗略的算一筆帳:瀏覽器
假設編譯一次要3分鐘,一天編譯40次緩存
- 天天花費:2小時等待編譯
- 一週花費:14小時等待編譯
- 一個月花費:60小時等待編譯 => 2.5天
每月花2.5天是在等待Gradle編譯,多呆哦,因此,讓Gradle編譯提速,顯得格外重要, 本節就從方方面面說下減小這個等待的時間吧。bash
大部分的Gradle編譯卡和慢,都是由於電腦配置的緣由,我的感受關鍵基本配置以下:app
- CPU:i5系列就夠了
- 內存:重要!至少要8G,有條件建議上16G
- 硬盤:重要!必須是SSD固態硬盤,窮一點的上128G,稍微寬裕點上256
其餘好比顯卡啊啥的沒什麼太大影響,配置確定是越高越好,在本身的經濟承受範圍之內便可。jvm
電腦配置差很少了,接下來就要調整下AS的可以使用內存,打開AS在右下角能夠看到使用內存和分配內存,如圖所示:maven
若是你的AS裏沒有這個圖的話,能夠依次點擊菜單欄的:「File」->「Settings」->「Appearance % Behavior」-> 「Appearance」-> 找到如圖所示的「Show memory indicator」勾選,而後點擊OK,就能夠在狀態欄看到內存分配信息了。ide
接着咱們來修改AS的內存分配,來到AS的安裝目錄下,進入bin目錄,找到:
用文本編輯類軟件打開對應文件,內容以下:
-Xms256m
-Xmx1280m
-XX:ReservedCodeCacheSize=240m
-XX:+UseConcMarkSweepGC
-XX:SoftRefLRUPolicyMSPerMB=50
-Dsun.io.useCanonCaches=false
-Djava.net.preferIPv4Stack=true
-Djna.nosys=true
-Djna.boot.library.path=
-da
複製代碼
接着咱們修改下前三項,改爲更大的值:
-Xms512m //JVM啓動的起始堆內存,堆內存是分配給對象的內存
-Xmx2560m //Java虛擬機啓動時的參數,用於限制最大堆內存
-XX:ReservedCodeCacheSize=480m //JIT java compiler在compile的時候的最大代碼緩存
-XX:+UseConcMarkSweepGC
-XX:SoftRefLRUPolicyMSPerMB=50
-Dsun.io.useCanonCaches=false
-Djava.net.preferIPv4Stack=true
-Djna.nosys=true
-Djna.boot.library.path=
複製代碼
修改完後保存,而後回到AS中,依次點擊菜單欄:「File」->「Ivalidate Caches/Restart...」,點擊後出現如圖對話框,點擊「Ivalidate Caches/Restart...」。
而後等待AS重啓便可。而後右下角能夠看到可用內存已經發生了改變,AS明顯打開流暢多了。
Dex-in-process容許你dex和gradle構建在同一個進程進行,以此加快增量構建和乾淨構建的速度。 要使用dex-in-process很是簡單:確保 grale 進程有足夠的內存分配給 dex 步驟來完成整個操做。 建議的公式:
Gradle memory >= Dex memory + 1Gb !
複製代碼
就是分配給gradle的內存比dex的內存多1g,dex進程內存設置在開發module的 build.gradle裏面控制。添加以下內容:
除此以外,dexOptions中還能夠添加下述配置:
//使用增量模式構建
incremental true
//是否支持大工程模式
jumboMode = true
//預編譯
preDexLibraries = true
//線程數
threadCount = 8
複製代碼
配置完dex,接着要配置gradle,打開「gradle.properties」修改org.gradle.jvmargs 的大小,按照公式,多1g,因此這裏配置成2g:
org.gradle.jvmargs=-Xmx2g
複製代碼
除此以外設置下JVM最大容許分配的非堆內存,以及堆內存移除時輸出堆的內存快照。
org.gradle.jvmargs=-Xmx2g -XX:MaxPermSize=0.5g -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
複製代碼
接着能夠再Terminal中中鍵入gradlew clean build來看看構建的速度是否加快了。 通常dex設置爲1-2G,gradle設置爲2-4G就能夠了,分配更多的內存並不會使構建加快多少!
除了配置給gradle分配的內存外,還能夠經過添加下述配置使得構建加快:
#開啓守護線程
org.gradle.daemon=true
#開啓並行編譯任務
org.gradle.parallel=true
#開啓緩存
android.enableBuildCache=true
複製代碼
另外,你還能夠在下述目錄中建立一個gradle.properties文件,全局生效,就不用每一個項目都另外配置了, 固然你喜歡仍是能夠在項目中建立這個文件。
就是使用阿國內阿里雲的依賴下載地址替換Google依賴包下載地址,打開Project級別的build.gradle文件,添加阿里雲的地址:
repositories {
maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' }
maven { url 'http://maven.aliyun.com/nexus/content/repositories/jcenter' }
...
}
allprojects {
repositories {
maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' }
maven { url 'http://maven.aliyun.com/nexus/content/repositories/jcenter' }
...
}
}
複製代碼
若是你的項目比較穩定,沒有什麼新的依賴(第三方庫引用),可使用這種方法來提高編譯速度。 依次點擊菜單欄「Setting」->「Build」-> 「Gradle」,找到如圖的「Offline work」勾選,點擊OK便可。
也能夠不配置,在命令行編譯的時候加上**--offline
**,好比:
gradlew build --offline
複製代碼
在引用依賴庫的時候,儘可能避免使用+這種動態版本號,而儘可能使用靜態編碼編碼版本號, 若是用動態版本號,每次編譯的時候Gradle會去檢查是否有更新,好比:
# 動態版本號
com.android.tools.build:gradle:3.2.+
# 靜態版本號
com.android.tools.build:gradle:3.2.1
複製代碼
你能夠經過下述兩種方式,查看編譯的時候都執行了哪些Task,以及他們的耗時。
方法一:經過gradlew --profile
編譯命令後加上--profile,好比 gradlew build --profile
,會輸出打包過程的profile report。
接着按照給出的路徑找到對應的html文件,用瀏覽器打開,點擊「Task Execution」
而後就能夠看到全部執行的Task和所需的耗時。除此以外,還能夠
方法二:使用build scan(構建審視)
Gradle 官方推出的一個可視化診斷工具,官網地址:gradle.com/build-scans…,不一樣的Gradle版本對應的 build-scan-plugin的版本也不一樣,能夠在官網查看對應的版本號:Gradle Enterprise version compatibility, 好比個人4.6對應最低版本的build scan工具的版本號爲:1.8。接着在項目級別的build.gradle文件中添加相關代碼:
buildscript {
repositories {
maven {
url "https://plugins.gradle.org/m2/"
}
}
dependencies {
classpath "com.gradle:build-scan-plugin:1.8"
}
}
apply plugin: "com.gradle.build-scan"
複製代碼
接着命令鍵入:gradlew build --scan,編譯完會問你是否Push到gradle.com,鍵入: yes便可。
若是不想每次都鍵入yes,在build.gradle中添加下述代碼:
buildScan {
licenseAgreementUrl = 'https://gradle.com/terms-of-service'
licenseAgree = 'yes'
}
複製代碼
接着點擊打開連接,會讓你輸入一個接收報告的郵箱:
接着會受到一個郵件,點開就能看到本次編譯的相關信息了,好比這裏看到佔較多編譯時間的Task是lint:
行吧,從上面的兩個例子咱們能夠明顯的看到lint耗時很多,而Lint在Debug階段並不須要,咱們能夠下述三種方式來禁用:
gradlew build -x lint -x lintVitalRelease
複製代碼
項目級別的build.gradle中buildScript添加下述代碼:
gradle.startParameter.excludedTaskNames.add('lint')
gradle.startParameter.excludedTaskNames.add('lintVitalRelease')
複製代碼
在模塊級別的build.gradle中的
apply plugin: 'com.android.application'
複製代碼
前加上下述代碼:
tasks.whenTaskAdded { task ->
if (task.name.contains("lint") || task.name.contains("lintVitalRelease")) {
task.enabled = false
}
}
複製代碼
Gradle在編譯時會執行大量Task,生成不少中間文件,會致使磁盤IO擁堵,形成編譯變慢, 能夠減小本地庫依賴,多使用aar進行依賴。
若是你不須要兼容低版本的設備的話,能夠把minSdkVersion改成21以上(Android 5.0),使用ART,在Build時只作class to dex, 而不作mergeing dex,一樣會節省一點的時間。
注:Gradle版本需大於3.4,示例以下:
compile 'com.android.support:appcompat-v7:28.0.0'
# 改成:
implementation 'com.android.support:appcompat-v7:28.0.0'
複製代碼
一樣的替換還有:
有效減小圖片文件大小,沒必要執行構建時壓縮,從而加快構建速度,若是你的APP用到大量圖片資源的話,效果明顯。
若是不想把圖片替換成WebP,可在每次構建應用時停用自動圖像壓縮的方式加快構建速度。模塊級別build.gradle添加下述代碼:
android {
...
aaptOptions {
cruncherEnabled false
}
}
複製代碼
直接**gradlew build
和執行gradlew assemble
** 會同時編譯生成Debug和Release的包,在調試階段其實 咱們可使用:
gradlew assembleDebug
複製代碼
來只編譯Debug版本的包,除此以外還能夠用另外一個命令編譯完直接安裝到設備上:
gradlew installDebug
複製代碼
同理對應Release的命令爲:
gradlew assembleRelease
gradlew installRelease
複製代碼
行吧,關於Gradle編譯提速大概就這些,有補充的歡迎在評論區留言,謝謝~
參考文獻:
歡迎你們加入開發交流羣一塊兒討論學習,能夠添加下述的機器人小號 RobotPig,發送『菜單』 輸入對應的提示,加入對應的開發羣(Android或Python),或者在公衆號『摳腚男孩』中發送加羣~
半自動拉人,會有延時,請諒解~