Android應(yīng)用構(gòu)建速度提升的十個(gè)小技巧
應(yīng)用的構(gòu)建速度會(huì)直接影響開(kāi)發(fā)效率,本文將帶您通過(guò)改造一個(gè) Android 應(yīng)用: “Google 追蹤圣誕老人 (Google Santa Tracker)” 來(lái)為大家提供十個(gè)小技巧,幫助提升應(yīng)用的 Gradle 構(gòu)建速度,當(dāng)我們應(yīng)用了所有的小技巧之后,該演示應(yīng)用的構(gòu)建速度快了三倍以上。
其次,在我們開(kāi)啟速度提升調(diào)優(yōu)之前,來(lái)了解本次三個(gè)性能指標(biāo)的說(shuō)明:
-
全量構(gòu)建,也就是重新開(kāi)始編譯整個(gè)工程的 debug 版;
-
代碼增量構(gòu)建,指的是我們修改了工程的 Java / Kotlin 代碼;
-
資源增量構(gòu)建,指的是我們對(duì)資源文件的修改,增加減少了圖片和字符串資源等。
小技巧 1: 使用最新版本的 Android Gradle 插件
每次 Android Gradle 插件的更新都會(huì)修復(fù)大量的 bug 及提升性能等新特性,因此保持最新的 Android Gradle 插件版本有非常大的必要。
從 3.0 版本開(kāi)始,我們將通過(guò) google() 的 Maven 倉(cāng)庫(kù)分發(fā)新的 Android Gradle 插件,所以需要在 repositories 處加入 google() 以獲得最新的插件更新 (現(xiàn)在的 Android Studio 新建工程的時(shí)候會(huì)默認(rèn)加入 google() 的 Maven 倉(cāng)庫(kù)指向)。
這是將 Android Gradle 插件版本從 2.x 更新到 3.0.0-alpha1 之后得到的結(jié)果 (這里的演示是基于 3.0.0-alpha1 版本,隨著插件版本的更新,性能的提升會(huì)更加明顯),我們可以看出,全量構(gòu)建一次應(yīng)用的時(shí)間直接減少了 25%,代碼改動(dòng)的增量構(gòu)建減少了將近 40%,資源改動(dòng)的增量構(gòu)建也減少了 16%。
小技巧 2: 避免激活舊版的 Multidex
啟用 multidex https://developer.android.google.cn/studio/build/multidex.html
如果您是通過(guò) Android Studio 的運(yùn)行/調(diào)試按鈕來(lái)執(zhí)行構(gòu)建,那么無(wú)需考慮這個(gè)問(wèn)題,新版本的 Android Studio 會(huì)自動(dòng)檢測(cè)連接的設(shè)備和模擬器,如果系統(tǒng)的 API 級(jí)別大于 21 則進(jìn)行原生的 multidex 支持,同時(shí)會(huì)忽略工程里對(duì)最低 API 級(jí)別 (minSdkVersion) 的設(shè)置。
這一次的性能改進(jìn)結(jié)果效果也非常明顯 (灰色的線條是最初的結(jié)果),在全量構(gòu)建的時(shí)候我們又降低了 5.5 秒的時(shí)間,而在代碼改動(dòng)的增量構(gòu)建里時(shí)間減少了 50% 以上,資源改動(dòng)的增量構(gòu)建與之前的時(shí)間相同。
小技巧 3: 禁用 Multiple APK 構(gòu)建
禁用多 APK 構(gòu)建不能僅僅在 splits 里設(shè)置,因?yàn)檫@里的設(shè)置對(duì)工程里所有的構(gòu)建變體都是可見(jiàn)的。正確的禁用多 APK 構(gòu)建的方法是創(chuàng)建一個(gè)屬性來(lái)做判斷,這里我們?cè)O(shè)置了一個(gè)名為 “devBuild” 的屬性,在構(gòu)建的過(guò)程中把這個(gè)值傳給 gradle,此時(shí) gradle 會(huì)將 splits.abi.enable 和 splits.density.enable 設(shè)置為 false,它就不會(huì)生成多個(gè) APK 了。
在 Android Studio 里,您可以通過(guò)偏好設(shè)置,構(gòu)建、執(zhí)行和部署分類里,選擇編譯器選項(xiàng)來(lái)為命令行加入?yún)?shù): -PdevBuild,這樣每次在構(gòu)建的時(shí)候 Android Studio 會(huì)把這個(gè)值傳遞給 gradle 以避免生成多個(gè) APK。
如上圖所示,這是我在禁用了多 APK 之后的效果,各項(xiàng)指標(biāo)都在繼續(xù)降低。
-
Multiple APK
https://developer.android.google.cn/google/play/publishing/multiple-apks.html
-
構(gòu)建變體
https://developer.android.google.cn/studio/build/build-variants.html
小技巧 4: 最小化使用資源文件
這里我們看到了較大程度上的改觀,全量構(gòu)建的時(shí)間又降低了 6 秒,增量構(gòu)建的時(shí)間也分別降低了 20% 以上。
小技巧 5: 禁用 PNG 壓縮
如果要避免使用 PNG 壓縮,我們可以在小技巧 3 里提到的,在 devBuild 屬性里加入 aaptOptions.cruncherEnabled = false 來(lái)實(shí)現(xiàn),在構(gòu)建的過(guò)程中把這個(gè)值傳給 gradle,它就可以避免執(zhí)行 PNG 壓縮命令了。
這可以看到全量構(gòu)建又減少了 9 秒的時(shí)間,這也是因?yàn)?Google 追蹤圣誕老人應(yīng)用里有 3,500 多張 PNG 圖片,這要花費(fèi)大量的時(shí)間進(jìn)行壓縮計(jì)算,所以這方面的效率提升顯得很明顯,而其他增量構(gòu)建只是維持了之前的情況。
小技巧 6: 使用 Apply Changes
從 Android Studio 3.5 版開(kāi)始 (3.5 版目前在 Beta 構(gòu)建渠道發(fā)布),開(kāi)發(fā)者們可以使用 Apply Changes 功能來(lái)提高構(gòu)建性能,它可以讓代碼和資源的改動(dòng)直接生效而無(wú)需重啟應(yīng)用,有時(shí)候甚至無(wú)需重啟當(dāng)前的 Activity。與 Instant Run 的實(shí)現(xiàn)方式不一樣,Apply Changes 充分利用了 Android 8.0 以上版本操作系統(tǒng)的特性進(jìn)行運(yùn)行時(shí)檢測(cè),從而動(dòng)態(tài)的對(duì)類進(jìn)行重新定義。因此,如果您希望使用 Apply Changes,則需要讓您的工程運(yùn)行在 Android 8.0 (API級(jí)別26) 以上的真機(jī)或者模擬器上。
小技巧 7: 避免被動(dòng)的改動(dòng)
這個(gè)例子里,我們故意在構(gòu)建腳本中加入里一些搗亂的代碼以展現(xiàn)其帶來(lái)的損失。同時(shí)也舉一個(gè)在使用 Crashlytics 時(shí)的實(shí)際例子,這個(gè)插件默認(rèn)會(huì)為每次構(gòu)建中都加入唯一 ID 作為構(gòu)建標(biāo)識(shí),這會(huì)帶來(lái)不必要的時(shí)間損失,您可以通過(guò)在構(gòu)建腳本里加入 ext.alwaysUpdateBuildId = false 來(lái)避免這個(gè),當(dāng)然也可以選擇在開(kāi)發(fā)階段完全關(guān)閉 Crashlytics。
小技巧 8: 不使用動(dòng)態(tài)版本標(biāo)識(shí)
Gradle 提供了一個(gè)非常方便的依賴庫(kù)版本號(hào)管理功能,方便開(kāi)發(fā)者們通過(guò)使用一個(gè)加號(hào) “+” 標(biāo)識(shí)希望使用這個(gè)依賴庫(kù)的最新版本。但是使用動(dòng)態(tài)版本有幾個(gè)風(fēng)險(xiǎn),從性能角度來(lái)說(shuō),Gradle 會(huì)每隔 24 小時(shí)去檢查一次依賴庫(kù)的更新,如果您的依賴庫(kù)很多,而且都使用了動(dòng)態(tài)獲取最新版本的這個(gè)設(shè)定,那會(huì)對(duì)構(gòu)建時(shí)候的性能產(chǎn)生一定的影響。
即使您不是特別在意這些性能損耗,但是它仍然是有風(fēng)險(xiǎn)的——依賴庫(kù)的版本更新會(huì)讓您的構(gòu)建充滿不確定性,可能兩周之后您就在構(gòu)建一個(gè)完全不一樣的工程了,因?yàn)橐蕾噹?kù)代碼的更新對(duì)開(kāi)發(fā)者們是不可見(jiàn)的。
小技巧 9: Gradle 內(nèi)存分配調(diào)優(yōu)
小技巧 10: 開(kāi)啟 Gradle 構(gòu)建緩存
關(guān)于 Gradle 構(gòu)建緩存 https://docs.gradle.org/current/userguide/build_cache.html
總結(jié)
代碼倉(cāng)庫(kù) https://github.com/jmslau/santa-tracker-android 官方文檔 https://developer.android.google.cn/studio/build/optimize-your-build