應用的構建速度會直接影響開發效率,本文將帶您經過改造一個 Android 應用: 「Google 追蹤聖誕老人 (Google Santa Tracker)」 來爲你們提供十個小技巧,幫助提高應用的 Gradle 構建速度,當咱們應用了全部的小技巧以後,該演示應用的構建速度快了三倍以上。html
首先來了解一下 「Google 追蹤聖誕老人」 應用的工程背景: 這個應用有約 60M 大小,它包含 9 個模塊,有 500 多個 Java 文件,1,700 多個 XML 文件、3,500 多張 PNG 圖片資源,用到了 Mutil-dex,沒有註解處理器。 其次,在咱們開啓速度提高調優以前,來了解本次三個性能指標的說明:java
每一個小技巧實施之後,咱們會對好比上三個場景的構建時間以做爲咱們的量化標準。請注意,因爲工程規模大小不1、開發環境各異,開發者們在實際的操做中的結果可能會與本文的結果有所不一樣。android
每次 Android Gradle 插件的更新都會修復大量的 bug 及提高性能等新特性,所以保持最新的 Android Gradle 插件版本有很是大的必要。緩存
從 3.0 版本開始,咱們將經過 google() 的 Maven 倉庫分發新的 Android Gradle 插件,因此須要在 repositories 處加入 google() 以得到最新的插件更新 (如今的 Android Studio 新建工程的時候會默認加入 google() 的 Maven 倉庫指向)。ide
這是將 Android Gradle 插件版本從 2.x 更新到 3.0.0-alpha1 以後獲得的結果 (這裏的演示是基於 3.0.0-alpha1 版本,隨着插件版本的更新,性能的提高會更加明顯),咱們能夠看出,全量構建一次應用的時間直接減小了 25%,代碼改動的增量構建減小了將近 40%,資源改動的增量構建也減小了 16%。性能
這個小技巧你們應該比較熟悉——避免激活舊版的 multidex。當您的應用配置方法數超過 64K 的時候,您須要啓用 multidex。當您啓用了 multidex,且工程的最低 API 級別在 21 以前時,舊版的 multidex 就會被激活,這將嚴重拖慢您的構建速度,緣由是 21 以前的 API 級別並無原生的支持 multidex。gradle
啓用 multidex developer.android.google.cn/studio/buil…優化
若是您是經過 Android Studio 的運行/調試按鈕來執行構建,那麼無需考慮這個問題,新版本的 Android Studio 會自動檢測鏈接的設備和模擬器,若是系統的 API 級別大於 21 則進行原生的 multidex 支持,同時會忽略工程裏對最低 API 級別 (minSdkVersion) 的設置。ui
習慣經過命令行窗口構建工程的開發者們則須要試着避免這個問題: 配置一個新的 productFlavor,設定工程的最低 API 級別爲 21 或者以上,在命令行裏調用 assembleDevelopmentDebug 便可避免這個問題。google
這一次的性能改進結果效果也很是明顯 (灰色的線條是最初的結果),在全量構建的時候咱們又下降了 5.5 秒的時間,而在代碼改動的增量構建裏時間減小了 50% 以上,資源改動的增量構建與以前的時間相同。
在應用須要發佈和上架的時候,咱們每每會使用 「Multiple APK」 構建,它能夠根據 ABI 和像素密度建立不一樣版本的應用,使包體積下降等。但這個在開發階段彷佛顯得有些多餘,因此咱們須要禁用多 APK 構建特性以提升構建速度。
禁用多 APK 構建不能僅僅在 splits 裏設置,由於這裏的設置對工程裏全部的構建變體都是可見的。正確的禁用多 APK 構建的方法是建立一個屬性來作判斷,這裏咱們設置了一個名爲 「devBuild」 的屬性,在構建的過程當中把這個值傳給 gradle,此時 gradle 會將 splits.abi.enable 和 splits.density.enable 設置爲 false,它就不會生成多個 APK 了。
在 Android Studio 裏,您能夠經過偏好設置,構建、執行和部署分類裏,選擇編譯器選項來爲命令行加入參數: -PdevBuild,這樣每次在構建的時候 Android Studio 會把這個值傳遞給 gradle 以免生成多個 APK。
如上圖所示,這是我在禁用了多 APK 以後的效果,各項指標都在繼續下降。
Multiple APK developer.android.google.cn/google/play… 構建變體 developer.android.google.cn/studio/buil…
當您的應用包含大量本地化資源或者爲不一樣像素密度加入了特別的資源時,您可能須要應用這個小技巧來提升構建速度——最小化開發階段打包進應用的資源數量。
構建系統默認會將聲明過或者使用過的資源所有打包進 APK,但在開發階段咱們可能只用到了其中一套而已,針對這種狀況,咱們須要使用 resConfigs() 來指定構建開發版本時所須要用到的資源,如語言版本和屏幕像素密度。
這裏咱們看到了較大程度上的改觀,全量構建的時間又下降了 6 秒,增量構建的時間也分別下降了 20% 以上。
與小技巧 4 同樣,這個特性自己在打包發佈階段是至關有幫助的—— PNG 壓縮,但在開發階段禁用這個功能能夠提升構建效率。默認狀況下,AAPT 會壓縮工程的 PNG 資源以減少 APK 體積,根據圖片的數量和大小,這個過程所消耗的時間有長有短。
若是要避免使用 PNG 壓縮,咱們能夠在小技巧 3 裏提到的,在 devBuild 屬性里加入 aaptOptions.cruncherEnabled = false 來實現,在構建的過程當中把這個值傳給 gradle,它就能夠避免執行 PNG 壓縮命令了。
另一個避免壓縮 PNG 的方法是使用把 PNG 轉換成 WebP 格式的圖片,對比 PNG 格式,WebP 能夠減小最多 25% 的大小,同時 2.3 以上版本的 Android Studio 直接支持 PNG 到 WebP 格式的轉換。
須要注意的是,API 級別 15 及更高能夠支持不透明的 WebP 格式圖片,若是是透明格式的 WebP,須要 API 級別 18 以及更高。
這能夠看到全量構建又減小了 9 秒的時間,這也是由於 Google 追蹤聖誕老人應用裏有 3,500 多張 PNG 圖片,這要花費大量的時間進行壓縮計算,因此這方面的效率提高顯得很明顯,而其餘增量構建只是維持了以前的狀況。
特別提出一下關於 APK 體積的問題——對比了啓用和禁用 PNG 壓縮以後的 APK 體積以後,咱們發現先後的體積並無太大改變,這說明該工程裏使用的 PNG 圖片在導入以前已經通過了充分優化,PNG 壓縮在這裏實屬畫蛇添足。
從 Android Studio 3.5 版開始 (3.5 版目前在 Beta 構建渠道發佈),開發者們可使用 Apply Changes 功能來提升構建性能,它可讓代碼和資源的改動直接生效而無需重啓應用,有時候甚至無需重啓當前的 Activity。與 Instant Run 的實現方式不同,Apply Changes 充分利用了 Android 8.0 以上版本操做系統的特性進行運行時檢測,從而動態的對類進行從新定義。所以,若是您但願使用 Apply Changes,則須要讓您的工程運行在 Android 8.0 (API級別26) 以上的真機或者模擬器上。
咱們經過一個很小的例子來講明這個小技巧: 咱們把工程的版本號設定爲基於當前時間的數字 (實際上你們應該不會這麼操做),這樣的結果是每次構建的時候版本號都是新的,工程的清單文件會所以發生改變,最後帶來的結果就是拖慢了本次的構建速度。
如圖所示,咱們發現增量構建的時間甚至增長了一倍,所以儘可能不要在構建腳本里加入太多無心義的內容。
解決這個問題並不難,咱們能夠經過在構建腳本里判斷是否有 devBuild 標記,若是有的話,咱們就把版本號設置爲一個固定值就能夠了。
這個例子裏,咱們故意在構建腳本中加入裏一些搗亂的代碼以展示其帶來的損失。同時也舉一個在使用 Crashlytics 時的實際例子,這個插件默認會爲每次構建中都加入惟一 ID 做爲構建標識,這會帶來沒必要要的時間損失,您能夠經過在構建腳本里加入 ext.alwaysUpdateBuildId = false 來避免這個,固然也能夠選擇在開發階段徹底關閉 Crashlytics。
Gradle 提供了一個很是方便的依賴庫版本號管理功能,方便開發者們經過使用一個加號 「+」 標識但願使用這個依賴庫的最新版本。可是使用動態版本有幾個風險,從性能角度來講,Gradle 會每隔 24 小時去檢查一次依賴庫的更新,若是您的依賴庫不少,並且都使用了動態獲取最新版本的這個設定,那會對構建時候的性能產生必定的影響。
即便您不是特別在乎這些性能損耗,可是它仍然是有風險的——依賴庫的版本更新會讓您的構建充滿不肯定性,可能兩週以後您就在構建一個徹底不同的工程了,由於依賴庫代碼的更新對開發者們是不可見的。
默認的構建環境裏,咱們會給 Gradle 分配 1.5G 的內存,但這個並不是適用於全部的項目,您須要經過對這個數字對調優來獲得適合您工程的最佳 Gradle 內存分配。
與此同時,從 Android Gradle 插件 2.1 版本以後,dex 已經默認在進程裏了,因此若是您以前設定過 javaMaxHeapSize 值,能夠選擇刪掉它了。
Gradle 新推出的緩存機制效果很是出色,咱們建議你們嘗試開啓,最新的 Gradle 支持了 Kotlin 項目使用構建緩存,構建速度能夠提升不少。Gradle 的構建緩存默認是不開啓的,您能夠經過在命令行里加入 --build-cache 參數或者在工程根目錄的 gradle.properties 里加入 org.gradle.caching=true 爲全部人啓用構建緩存。您能夠在這個文檔裏瞭解更多關於 Gradle 構建緩存的內容。
在實踐了全部的速度提高小技巧以後,獲得的總體的改善結果,全量構建的速度比以前快了三倍以上,而代碼改動的增量構建則快了 12 倍以上。