一種app模組化實現方案

尼古拉斯_趙發表於2019-04-26

模組化的優勢有很多,一程式碼分離,結構清晰;二多工協同開發,而且自己模組單獨執行也更輕量。等等。最近在調研各種實現方案,這是我的自己想出來的一種。

話不多說,直接分享我的操作步驟,然後我可能會與其他實現方式做個對比。

原有專案結構

為了實現模組化,前期我們已經根據應用功能場景,進行了module拆分,為實現模組化靠攏。專案簡化結構如下圖

一種app模組化實現方案

APP是應用的入口module,我把他做得很簡單,裡邊可以說就一個歡迎頁Activity。BaseModule是一些跟基本封裝。ModuleA、B、C是期望單獨執行的Module。模組間的跳轉我用的是ARouter,這塊暫不多介紹。

我們知道,每一個Project都是由多個module組成,而settings.gradle中通過include方式引入這些module,所以一開始就在想如果能在編譯時動態的引入module那不就是很簡單了嗎。

操作步驟

一 gradle.properties配置

在專案根目錄的gradle.properties中定義一個變數,為了做到變數值的見名知意,我用的String型別的

	# ↓全量編譯模式
	#DEVELOP_MODE="all"
	#
	# ↓單ModuleA模組編譯模式
	DEVELOP_MODE="module-a"
	#
	# ↓單ModuleB模組編譯模式
	#DEVELOP_MODE="module-b"
	#
	# ↓單ModuleC模組編譯模式
	#DEVELOP_MODE="module-c"
	#
	...
複製程式碼

二 settings.gradle區分

根據gradle.properties中配置的不同執行模式,在settings中做簡單的if else 判斷,include不同的module

	include ':APP', 'BaseModule'
	if (DEVELOP_MODE == "\"module-a\"") {
	    include ':ModuleA'
	} else if (DEVELOP_MODE == "\"module-b\"") {
	    include ': ModuleB'
	} else if (DEVELOP_MODE == "\"module-c\"") {
	    include ': ModuleC'
	} else {
	    include ': ModuleA', ': ModuleB', ': ModuleC'
	}
複製程式碼

在這裡有個寫法上需要注意的是String型別的module-a需要加\轉義,甚至呼叫startsWith這樣的API都要這樣寫DEVELOP_MODE.startsWith("\"module")

有人說這裡不需要區分,直接include所有module即可。我嘗試後發現確實可以,但仍會執行多餘module的gradle編譯,徒增編譯時間,所以最好區分。

三 APP的gradle配置

上面的module關係依賴圖中我們看到,APP依賴了A、B、C這三個module。在這裡,我們也是需要根據gradle.properties中配置的不同執行模式,動態引入依賴

	if (DEVELOP_MODE == "\"module-a\"") {
	    implementation project(':ModuleA')
	} else if (DEVELOP_MODE == "\"module-b\"") {
	    implementation project(':ModuleB')
	} else if (DEVELOP_MODE == "\"module-c\"") {
	    implementation project(':ModuleC')
	} else {
	    implementation project(':ModuleA')
	    implementation project(':ModuleB')
	    implementation project(':ModuleC')
	}
複製程式碼

好了,一個簡單的模組化就實現了,如果想單獨執行ModuleA,就將gradle.properties中的DEVELOP_MODE="module-a"這一行解開,其他註釋掉,sync Now完後直接執行就OK了

擴充

一個正常的商業專案,肯定不像我前面的專案圖一樣簡單,只有1個APP、1個Base、2個Module。我專案真實情況是類似中間的模組ABC這層就有20多個,而且不止一層;Base這層module也有五六個。不使用JIMU(積木)那種Android元件化框架的原因之一就是專案不是簡簡單單,關係整齊的這種依賴關係。

而且,在我們應用裡,要想使用ModuleB,必須帶著ModuleA的結果資料。要想B模組化後能使用,這該怎麼做?需要的資料可能有:資料庫、SharedPreferences、File檔案,網路請求及合理的引數。

我們的做法是,為這種非正式的模組化執行新增一個,專門初始化假資料的module。在APP的歡迎頁中跳轉時判斷,如果是模組化執行,直接往這個假資料Module跳,通過這個Module初始化好所有的資料後,再往真正的目標Module跳。

而需要準備的資料中,網路請求及合理的引數的準備,也有很多實現方案。比如就用真實的請求,比如本機執行服務。對於我做這個調研,沒有找後端支援,也想過自己搭後臺伺服器,但是一想,搭好了伺服器,也是簡單的返回造好的假json串資料。所以乾脆,本地處理算了,這時候okhttp的攔截器就是一個很好的應用了。我直接在攔截器中,判斷請求的path,返回假的json串不就行了。

當然,還有很多模組化需要用到的小技術點,那就需要見招拆招了。

與其他模組化方式對比

(1)有一種模組化是這樣寫的,在ModuleA的gradle檔案中

	if(isBuildModule.toBoolean()){
	    apply plugin: 'com.android.application'
	}else{
	    apply plugin: 'com.android.library'
	}
	...
	    sourceSets {
	        main {
	            if (isBuildModule.toBoolean()) {
	                manifest.srcFile 'src/main/debug/AndroidManifest.xml'
	            } else {
	                manifest.srcFile 'src/main/release/AndroidManifest.xml'
	            }
	        }
	    }
	 
	 
	//isBuildModule是在gradle.properties中宣告
	isBuildModule=false
複製程式碼

這樣寫的繁瑣之處是

  • 需要在每個Module的gradle.properties中宣告這樣一個區分application還是library。
  • 準備兩套Manifest。
  • 要想單獨執行某個模組還得每次去改動settings的include,和APP的gradle中的依賴。

(2)使用JIMU(積木)這種Android元件化框架

它整合好之後的使用,雖然也很簡單。但是框架的接入也是需要新增很多東西,比如每個module的properties中都需要進行配置。而且框架的一個缺點就是我們開發人員不知道它怎麼實現的,遇到的編譯問題也更不好查。

(3)我這樣寫的優缺點

優點

  • 條理清晰,定義的每個地方是什麼作用都很清楚
  • 不修改原有module內的業務邏輯,在外邊準備好所需資料有點沙盒似的設計。
  • 不只能單模組執行。也可能,多個模組組成一個業務線,整體執行這個業務線也很好實現。
  • 切換執行模組時,只開關gradle.properties裡的配置就行。

缺點

  • 新配置一個模組化需要在gradle.properties、settings.gradle、APP的gradle,這3個地方都做響應的配置。需要配的模組化執行多了,if else 類的判斷也會增多,程式碼行數也會增加,略顯繁瑣。但相對於切換模組的簡便,這些是值得的。

最後求助各位道友,如果,您們有其他什麼好的思路,歡迎你們和我一起交流

相關文章