隨着app的持續迭代更新,新功能的持續集成等緣由。項目中的library project愈來愈多。android
特別是最近一兩年來。流行起來了組件化,這更是直接增長了不少的本地library project的數量。致使每次須要打包apk運行時,都會須要對全部module都進行再次編譯。嚴重影響打包速度。git
Speedup是一款專用於對多module環境下進行打包加速的gradle插件。主要依賴的基本原理有兩個:github
咱們先來看看常規多module環境下的打包流程:api
從上圖能夠看到。每次打包的時候。都會通過如下幾個步驟:bash
而若是。咱們使用maven依賴的方式進行依賴的話。編譯流程就會優化成下圖所示的方式:網絡
能夠看到。與上面直接使用module依賴的方式相比:使用Maven倉庫依賴的方式,因爲maven倉庫中提供的直接就是已打包好的aar依賴,因此直接幹掉了module -> aar打包編譯的過程,起到了加速編譯的做用!併發
因此,如今咱們就能夠得出第一個結論:使用maven依賴比使用module依賴更快速!app
因此這個時候。不少人的常規作法就是。想辦法將這些module依賴的library,編譯打包發佈到各自的遠程中央倉庫中去,這樣就能避免每次運行的時候都去進行額外編譯,從而節省時間了。maven
可是這種作法存在幾個問題:
因此將module打包發佈到遠程倉庫的作法,並不可取!
如今咱們來考慮一下,若是將倉庫設置在本地會怎樣?也就是說使用本地maven倉庫進行依賴管理。
咱們來列舉一下這裏使用本地依賴的優勢:
本地倉庫中version不惟一:
便可以作到同版本覆蓋發佈,修改代碼後直接從新發布便可,不須要提高version版本。這也正是遠程倉庫所作不到的。可避免頻繁升級改動。
本地倉庫不與網絡打交道。
讀取依賴更快速。事實上,遠程倉庫中所依賴的庫,也是先存放到本地倉庫中去再進行讀取的。
能夠看到,使用本地倉庫,能夠完美的解決頻繁發包的問題!由於若是你的library不須要頻繁修改的話,你確定也早就已經把它單獨拆出去放遠程倉庫中去了~
因此咱們只要解決依賴不統一的問題。那麼這個加速方案就算是完全打通了!
打包任務這裏特指的assembleXXX任務。這個任務相信你們平時也見過無數次了。
此任務是由android插件所提供的,編譯、合併、打包一條龍的總線任務。平時咱們點擊運行按鈕、打包apk時。也是經過的調用此任務進行打包。打包後經過內置的adb命令將apk發送到手機並執行安裝。
這個任務有個很重要的特性。這裏我稱之爲按需加載特性
打個比方:假如咱們使用的組件化開發模式,項目依賴鏈以下圖所示:
上圖所示的依賴鏈,對組件化不熟的可能會比較懵逼。對組件化有興趣的能夠去這裏瞭解一下組件化的項目結構:聚美組件化實踐之路
這裏有三個可運行的殼工程。其各自殼工程的依賴鏈以下:
而按需加載特性是指:在進行打包任務過程當中,打包任務只會觸發當前自身依賴鏈中的module進行編譯。而不會對別的非自身依賴鏈中的module進行編譯。
因此,當你運行app shell1的時候。這個時候會參與打包編譯的就是[app shell 1]、[component 1]、[base library]這三個module. 這就是按需加載特性
基於以上分析,我創建了此Speedup插件。利用gradle腳本,方便的進行本地aar打包發佈,並經過對打包任務流程進行監聽,動態的將module依賴替換爲本地倉庫中的maven依賴。
這裏我畫了個簡單的流程圖。便於直觀的理解此gradle插件的運行機制。
在項目根目錄下添加依賴並添加應用插件
buildscript {
repositories {
// 添加jitpack倉庫地址
maven { url "https://jitpack.io" }
}
dependencies {
// 添加插件依賴
classpath "com.github.yjfnypeu:Speedup:0.9"
}
}
// 應用插件
apply plugin: 'speedup'
複製代碼
Speedup支持配置三種屬性,均配置於項目根目錄下的local.properties文件中。
speedup.enable:
是否激活speedup插件。默認爲false,即不激活。這樣作的目的是爲了使得在發版機器上進行打包apk時。自動忽略speedup插件。進行全量編譯
localRepo:
本地maven倉庫的地址。默認爲項目根目錄下的_repo文件夾。若你須要使用別的地址。在此配置個本地地址便可
excludeModules:
因爲咱們開發的業務線的不一樣。不少時候咱們是須要對部分的module每次都進行即時編譯的:好比說如今正在作的功能。是須要對某個lib進行頻繁修改的。因此這個時候。就須要使用此屬性。指定此lib不須要進行加速。那麼每次運行時。都會對此lib進行編譯。
把全部屬性全放置於local.properties中,出於如下幾點考慮:
github上我提供了一個組件化demo地址, 此demo中有添加此插件配置使用。如下內容建議結合demo進行查看。
因爲本地配置是放置於local.properties文件當中。因此默認依賴下來是沒有開啓激活此插件的。能夠參考下方的配置:放入自身的local.properties中去。
speedup.enable=true
# 當須要排除多個module時,中間用英文的逗號隔開
excludeModules=:usercenter:componentusercenter
複製代碼
當配置speedup.enable爲true,而且同步完成以後。你就能夠在gradle任務列表中發現一組speedup任務:
能夠看到。speedup任務組中。含有大量的uploadXXX任務提供使用。這些任務都是在同步時根據各個library module自動生成的上傳任務。主要目的是將本地的library module方便的進行打包、編譯。併發布到本地的倉庫中去。提供使用。
當你使用upload進行本地打包發佈後,你就能夠在項目根目錄下的_repo文件夾下找到對應的打包出來的aar:
而後,你能夠試試直接運行。而且觀察右下角的Gradle Console控制檯輸出日誌。注意看全部執行的任務列表。就會發現:執行的gradle任務明顯減小了,而且被打包到本地中的module。並無被再次進行編譯。
這是由於已經在運行時。動態的將對應的module替換爲使用本地倉庫中的aar地址了。
以上便是此插件的整個用法示例。能夠總結爲如下幾步:
Speedup插件任務中,很重要的一點便是生成的upload任務列表了。此upload任務主要分爲三類:
uploadAll
做用:用於對項目中全部的library(除了excludeModules所指定排除的module)進行打包發佈。此任務默認將會對項目下全部的module執行clean操做。因此能夠保證打包出來的aar是不受數據污染的
使用場景:在進行分支切換後、或者進行合併代碼後。此時不少module的數據都有修改。可使用此任務一次性所有從新打包上傳。
uploadForClean
做用:用於觸發項目下全部module的clean任務。將其build文件夾刪除。避免打包時出現數據污染。
與AS自帶的clean任務不一樣。自帶的clean任務附帶了不少額外的任務,因此每次clean會很慢。而uploadForClean。只會觸發全部module自身的clean任務,對自身的build文件夾進行刪除,並沒有其餘額外操做。這樣clean的速度會獲得很大提高。
此任務通常來講外部不須要直接使用。主要是內部直接提供給uploadAll進行使用
uploadXXX
做用:用於對指定的module進行從新打包發佈。好比uploadbaselib。此任務表明對baselib從新進行打包發佈。