工欲善其事,必先利其器。如果每次運(yùn)行項(xiàng)目都要花費(fèi)5-10分鐘,那人的心態(tài)都要崩了。
Gradle構(gòu)建流程
Gradle 的生命周期可以分為大的三個(gè)部分:初始化階段(Initialization Phase)胎撇,配置階段(Configuration Phase),執(zhí)行階段(Execution Phase)殖氏。
優(yōu)化方案
從整體構(gòu)建流程可以得知晚树,我們整體上需要從三個(gè)方面進(jìn)行優(yōu)化:
- 初始化速度優(yōu)化
- 配置速度優(yōu)化
- 執(zhí)行速度優(yōu)化
其中執(zhí)行的過(guò)程占比是最大的,所以重心放在執(zhí)行速度優(yōu)化上雅采。
1.初始化速度優(yōu)化
當(dāng)組件化程度較高時(shí)爵憎,在開(kāi)發(fā)某個(gè)特定功能過(guò)程中有些組件是不需要引入的慨亲,此時(shí)可以在setting.gradle中移除不需要引入的組件模塊,可以減少初始化時(shí)間
2.配置速度優(yōu)化
配置階段主要是對(duì)各個(gè)build.gradle進(jìn)行解析宝鼓,因此可以注意以下幾點(diǎn):
按需引入模塊刑棵,減少build.gradle的解析
build.gradle中盡量少做耗時(shí)操作,例如讀取系統(tǒng)時(shí)間動(dòng)態(tài)配置apk的名稱(chēng)組成
在開(kāi)發(fā)階段不是必要執(zhí)行的任務(wù)愚铡,可以寫(xiě)判斷避免這些任務(wù)的配置蛉签,例如一些字節(jié)碼插樁,性能監(jiān)控之類(lèi)的沥寥。
-
開(kāi)啟Configuration Cache
在任務(wù)執(zhí)行階段碍舍,Gradle提供了多種方式實(shí)現(xiàn)Task的緩存與重用(如up-to-date檢測(cè),增量編譯邑雅,build-cache等)片橡。
除了任務(wù)執(zhí)行階段,任務(wù)配置階段有時(shí)也比較耗時(shí)淮野,目前AGP也支持了配置階段緩存Configuration Cache,它可以緩存配置階段的結(jié)果捧书,當(dāng)腳本沒(méi)有發(fā)生改變時(shí)可以重用之前的結(jié)果。
在越大的項(xiàng)目中配置階段緩存的收益越大骤星,module比較多的項(xiàng)目可能每次執(zhí)行都要先配置20到30秒经瓷,尤其是增量編譯時(shí),配置的耗時(shí)可能都跟執(zhí)行的耗時(shí)差不多了洞难,而這正是configuration-cache的用武之地了嚎。
目前Configuration-cache還是實(shí)驗(yàn)特性,如果你想要開(kāi)啟的話可以在gradle.properties中添加以下代碼:
# configuration cache
org.gradle.unsafe.configuration-cache=true
org.gradle.unsafe.configuration-cache-problems=warn
3.執(zhí)行速度優(yōu)化
-
開(kāi)啟并行編譯
開(kāi)啟后會(huì)并行執(zhí)行多個(gè)任務(wù)廊营,大幅度減少編譯時(shí)間,只需要在gradle.properties中添加:
org.gradle.parallel=true
-
增大編譯內(nèi)存
由于大家的電腦配置都不一樣萝勤,因此具體設(shè)置多大內(nèi)存需要根據(jù)個(gè)人情況進(jìn)行合理配置露筒,一般在gradle.properties里已經(jīng)有相關(guān)配置,可以對(duì)該配置進(jìn)行修改敌卓,例如
org.gradle.jvmargs=-Xmx4096m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
同時(shí)在主工程模塊的build.gradle中進(jìn)行修改:
dexOptions {
javaMaxHeapSize "4g"
}
-
開(kāi)啟按需構(gòu)建
對(duì)沒(méi)有更改的模塊不再進(jìn)行編譯慎式,非常適合已經(jīng)組件化的項(xiàng)目,在gradle.properties中添加:
org.gradle.configureondemand=true
-
開(kāi)啟構(gòu)建緩存
直接使用之前生成的緩存趟径,不再進(jìn)行構(gòu)建瘪吏,在構(gòu)建時(shí)任務(wù)后面會(huì)顯示FROM CACHE,在gradle.properties中添加:
org.gradle.caching=true
-
開(kāi)啟增量注解編譯
支持注解增量編譯蜗巧,不會(huì)重新觸發(fā)編譯(gradle高版本中需要移除)掌眠,在gradle.properties中添加:
android.enableSeparateAnnotationProcessing=true
4.其他速度優(yōu)化
-
對(duì)AS進(jìn)行配置
開(kāi)啟離線模式
開(kāi)啟離線模式后不會(huì)再開(kāi)始的時(shí)候去檢測(cè)依賴(lài)是否有更新,也不會(huì)去下載相關(guān)更新的依賴(lài)幕屹,首次構(gòu)建不能開(kāi)啟蓝丙,否則無(wú)法完成構(gòu)建级遭,后續(xù)構(gòu)建可以開(kāi)啟,在某些情況下將大幅度改善編譯速度渺尘,強(qiáng)烈推薦開(kāi)發(fā)階段使用挫鸽。點(diǎn)擊下圖中的圖標(biāo)的按鈕即可開(kāi)啟離線模式,有些版本顯示為類(lèi)似wifi的圖標(biāo)鸥跟,再次點(diǎn)擊取消離線模式:
-
更改AS內(nèi)存大小
點(diǎn)擊AS的Help菜單項(xiàng)丢郊,選中Change Memory Settings選項(xiàng)。
-
KAPT 遷移到 KSP
注解處理器是Android開(kāi)發(fā)中一種常用的技術(shù)医咨,很多常用的框架比如ButterKnife枫匾,ARouter,Glide中都使用到了注解處理器相關(guān)技術(shù)腋逆。
但是如果項(xiàng)目比較大的話婿牍,會(huì)很容易發(fā)現(xiàn)KAPT是拖慢編譯速度的常見(jiàn)原因,這也是谷歌推出KSP取代KAPT的原因惩歉。
-
關(guān)閉R文件傳遞
在 apk 打包的過(guò)程中等脂,module 中的 R 文件采用對(duì)依賴(lài)庫(kù)的R進(jìn)行累計(jì)疊加的方式生成。如果我們的 app 架構(gòu)如下:
編譯打包時(shí)每個(gè)模塊生成的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.關(guān)閉R文件傳遞可以通過(guò)編譯避免的方式獲得更快的編譯速度
2.關(guān)閉R文件傳遞有助于確保每個(gè)模塊的R類(lèi)僅包含對(duì)其自身資源的引用撑蚌,避免無(wú)意中引用其他模塊資源上遥,明確模塊邊界。
3.關(guān)閉R文件傳遞也可以減少很大一部分包體積與dex數(shù)量
從 Android Studio Bumblebee 開(kāi)始争涌,新項(xiàng)目的非傳遞 R 類(lèi)默認(rèn)處于開(kāi)啟狀態(tài)粉楚。即gradle.properties文件中都開(kāi)啟了如下標(biāo)記
android.nonTransitiveRClass=true
-
開(kāi)啟Kotlin跨模塊增量編譯
使用組件化多模塊開(kāi)發(fā)的同學(xué)都有經(jīng)驗(yàn),當(dāng)我們修改底層模塊(比如util模塊)時(shí)亮垫,所有依賴(lài)于這個(gè)模塊的上層模塊都需要重新編譯模软,Kotlin的增量編譯在這種情況往往是不生效的,這種時(shí)候的編譯往往非常耗時(shí)饮潦。
在Kotlin 1.7.0中燃异,Kotlin編譯器對(duì)于跨模塊增量編譯也做了支持,并且與Gradle構(gòu)建緩存兼容继蜡,對(duì)編譯避免的支持也得到了改進(jìn)回俐。這些改進(jìn)減少了模塊和文件重新編譯的次數(shù),讓整體編譯更加迅速稀并。
在 gradle.properties 文件中設(shè)置以下選項(xiàng)即可使用新方式進(jìn)行增量編譯:
kotlin.incremental.useClasspathSnapshot=true // 開(kāi)啟跨模塊增量編譯
kotlin.build.report.output=file // 可選仅颇,啟用構(gòu)建報(bào)告
-
Module源碼轉(zhuǎn)aar
隨著業(yè)務(wù)量的增大,module的引入也會(huì)增多碘举,每個(gè)module在編譯的時(shí)候都需要花費(fèi)一定的時(shí)間忘瓦。把module轉(zhuǎn)化成aar后就不再需要每次都進(jìn)行編譯或者取緩存,可以減少一部分時(shí)間殴俱。
參考:
https://mp.weixin.qq.com/s/q1zIhtTXvKubhg3HOG7T0Q
https://blog.csdn.net/Nbin_Newby/article/details/120439965