Android加快你的編譯速度

工欲善其事,必先利其器。如果每次運行項目都要花費5-10分鐘,那人的心態都要崩了。

Gradle構建流程

Gradle 的生命週期可以分爲大的三個部分:初始化階段(Initialization Phase),配置階段(Configuration Phase),執行階段(Execution Phase)。

優化方案

從整體構建流程可以得知,我們整體上需要從三個方面進行優化:

  • 初始化速度優化
  • 配置速度優化
  • 執行速度優化
    其中執行的過程佔比是最大的,所以重心放在執行速度優化上。
1.初始化速度優化

當組件化程度較高時,在開發某個特定功能過程中有些組件是不需要引入的,此時可以在setting.gradle中移除不需要引入的組件模塊,可以減少初始化時間

2.配置速度優化

配置階段主要是對各個build.gradle進行解析,因此可以注意以下幾點:

按需引入模塊,減少build.gradle的解析
build.gradle中儘量少做耗時操作,例如讀取系統時間動態配置apk的名稱組成
在開發階段不是必要執行的任務,可以寫判斷避免這些任務的配置,例如一些字節碼插樁,性能監控之類的。

  • 開啓Configuration Cache

在任務執行階段,Gradle提供了多種方式實現Task的緩存與重用(如up-to-date檢測,增量編譯,build-cache等)。

除了任務執行階段,任務配置階段有時也比較耗時,目前AGP也支持了配置階段緩存Configuration Cache,它可以緩存配置階段的結果,當腳本沒有發生改變時可以重用之前的結果。

在越大的項目中配置階段緩存的收益越大,module比較多的項目可能每次執行都要先配置20到30秒,尤其是增量編譯時,配置的耗時可能都跟執行的耗時差不多了,而這正是configuration-cache的用武之地。

目前Configuration-cache還是實驗特性,如果你想要開啓的話可以在gradle.properties中添加以下代碼:

# configuration cache
org.gradle.unsafe.configuration-cache=true
org.gradle.unsafe.configuration-cache-problems=warn
3.執行速度優化
  • 開啓並行編譯

開啓後會並行執行多個任務,大幅度減少編譯時間,只需要在gradle.properties中添加:

org.gradle.parallel=true
  • 增大編譯內存

由於大家的電腦配置都不一樣,因此具體設置多大內存需要根據個人情況進行合理配置,一般在gradle.properties裏已經有相關配置,可以對該配置進行修改,例如

org.gradle.jvmargs=-Xmx4096m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8

同時在主工程模塊的build.gradle中進行修改:

    dexOptions {
        javaMaxHeapSize "4g"
    }
  • 開啓按需構建

對沒有更改的模塊不再進行編譯,非常適合已經組件化的項目,在gradle.properties中添加:

org.gradle.configureondemand=true
  • 開啓構建緩存

直接使用之前生成的緩存,不再進行構建,在構建時任務後面會顯示FROM CACHE,在gradle.properties中添加:

org.gradle.caching=true
  • 開啓增量註解編譯

支持註解增量編譯,不會重新觸發編譯(gradle高版本中需要移除),在gradle.properties中添加:

android.enableSeparateAnnotationProcessing=true
4.其他速度優化
  • 對AS進行配置

開啓離線模式
開啓離線模式後不會再開始的時候去檢測依賴是否有更新,也不會去下載相關更新的依賴,首次構建不能開啓,否則無法完成構建,後續構建可以開啓,在某些情況下將大幅度改善編譯速度,強烈推薦開發階段使用。點擊下圖中的圖標的按鈕即可開啓離線模式,有些版本顯示爲類似wifi的圖標,再次點擊取消離線模式:


  • 更改AS內存大小

點擊AS的Help菜單項,選中Change Memory Settings選項。


  • KAPT 遷移到 KSP

註解處理器是Android開發中一種常用的技術,很多常用的框架比如ButterKnife,ARouter,Glide中都使用到了註解處理器相關技術。

但是如果項目比較大的話,會很容易發現KAPT是拖慢編譯速度的常見原因,這也是谷歌推出KSP取代KAPT的原因。

  • 關閉R文件傳遞

在 apk 打包的過程中,module 中的 R 文件採用對依賴庫的R進行累計疊加的方式生成。如果我們的 app 架構如下:

編譯打包時每個模塊生成的R文件如下:

1. R_lib1 = R_lib1;
2. R_lib2 = R_lib2;
3. R_lib3 = R_lib3;
4. R_biz1 = R_lib1 + R_lib2 + R_lib3 + R_biz1(biz1本身的R)
5. R_biz2 = R_lib2 + R_lib3 + R_biz2(biz2本身的R)
6. R_app = R_lib1 + R_lib2 + R_lib3 + R_biz1 + R_biz2 + R_app(app本身R)

1.關閉R文件傳遞可以通過編譯避免的方式獲得更快的編譯速度
2.關閉R文件傳遞有助於確保每個模塊的R類僅包含對其自身資源的引用,避免無意中引用其他模塊資源,明確模塊邊界。
3.關閉R文件傳遞也可以減少很大一部分包體積與dex數量

從 Android Studio Bumblebee 開始,新項目的非傳遞 R 類默認處於開啓狀態。即gradle.properties文件中都開啓瞭如下標記

android.nonTransitiveRClass=true
  • 開啓Kotlin跨模塊增量編譯

使用組件化多模塊開發的同學都有經驗,當我們修改底層模塊(比如util模塊)時,所有依賴於這個模塊的上層模塊都需要重新編譯,Kotlin的增量編譯在這種情況往往是不生效的,這種時候的編譯往往非常耗時。

在Kotlin 1.7.0中,Kotlin編譯器對於跨模塊增量編譯也做了支持,並且與Gradle構建緩存兼容,對編譯避免的支持也得到了改進。這些改進減少了模塊和文件重新編譯的次數,讓整體編譯更加迅速。

在 gradle.properties 文件中設置以下選項即可使用新方式進行增量編譯:

kotlin.incremental.useClasspathSnapshot=true // 開啓跨模塊增量編譯
kotlin.build.report.output=file // 可選,啓用構建報告
  • Module源碼轉aar

隨着業務量的增大,module的引入也會增多,每個module在編譯的時候都需要花費一定的時間。把module轉化成aar後就不再需要每次都進行編譯或者取緩存,可以減少一部分時間。

參考:
https://mp.weixin.qq.com/s/q1zIhtTXvKubhg3HOG7T0Q
https://blog.csdn.net/Nbin_Newby/article/details/120439965

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章