一個完美支援多程序的元件化方案
寫在開頭
元件化技術適用於需要多人協作的中大型專案,如果是一個人的專案且開發人員未實踐過元件化方案則不建議採用。
元件化的優點
1.業務隔離,使得各業務模組專注於自己的業務實現,而不必關心其他業務模組.
2.單獨除錯,每個模組可以獨立執行,方便開發除錯.
3.元件可複用性,針對有重疊業務的不同APP,可直接使用元件來組裝.
4.適合AOP.
5.可以更細粒度的設定組員的程式碼修改許可權.
DRouter:完美支援多程序的元件化方案
demo下載
框架特點
* 完美支援多程序,且不需要使用者去bindService或自定義AIDL.
* 頁面路由:支援給Activity定義url,然後通過url跳轉到Activity,支援新增攔截器.
* 跨程序的事件匯流排.
* 支援跨程序的API呼叫.
* 充分實現模組解耦,頁面路由、API呼叫、事件匯流排均支援跨模組使用.
* 基於AOP引導Module的初始化以及頁面、攔截器、provider的自動註冊.
如何配置
1.在BaseModule中新增依賴:

2.在其他需要用到DRouter的元件中添加註解處理器的依賴:

3.多程序配置:
* 如果你的專案需要使用多程序廣域路由,那麼請讓你的Application實現 IMultiProcess 介面,廣域路由預設是關閉狀態,只有實現了該接口才會啟用。
* 在App module的build.gradle檔案中,且必須在apply plugin: 'com.android.application'之後引用編譯外掛RouterPlugin,具體如下:
```
apply plugin: 'com.android.application'
apply plugin: "com.dovar.router.plugin" //必須在apply plugin: 'com.android.application'之後,否則找不到AppExtension
buildscript {
repositories {
google()
maven {
url "https://plugins.gradle.org/m2/"
}
}
dependencies {
classpath "gradle.plugin.RouterPlugin:plugin:1.1.8"
}
}
```
如何使用
在Application.onCreate()中完成初始化
DRouter.init(app);
頁面路由

動作路由(API呼叫)

事件匯流排
訂閱事件

釋出事件(在任意執行緒)

退訂事件(通過subscribeForever()訂閱時,需要及時取消訂閱)

建立元件初始化入口(非必須)

DRouter的元件化實現
介面路由

動作路由

事件匯流排

元件化專案架構圖

關於APP殼工程
用於管理打包配置和設定元件引用.
關於應用元件層
業務中心,包括業務元件和功能元件(功能元件專指沒有UI邏輯的業務,注意區分,網路請求、圖片載入這些屬於基礎框架層).
關於公共服務層
管理跨元件呼叫和公共資源,詳細可參考專案中的common_service.
為什麼要在基礎框架層和應用元件層中間多架設一個公共服務層?
* 封裝對基礎框架層功能API的呼叫,方便應對日後更換第三方庫的需求,相信很多程式設計師都經歷過更換第三方庫(特別是基礎庫)的痛苦啦,
* 如果專案中沒有自己封裝而是直接引用第三方API的話,等到要換的時候就會發現需要修改的程式碼實在太多了。
* 儲存公用資源和程式碼,暴露給上層業務使用,同時避免這些資源被下沉到基礎框架層,從而減少對基礎框架層的非必要更新。
* 在多人協作專案中,基礎框架必須是穩定的,所以我們希望有儘可能少的commit指向基礎框架層。
關於基礎框架層
與業務無關的通用功能模組,如網路請求、圖片載入、通用的自定義控制元件等.
1.元件跳轉
支援給Activity定義path,然後通過path跳轉到Activity,可設定跳轉攔截器.
2.程序內元件間通訊機制
1. 服務提供者向DRouter註冊Action對其他元件暴露服務.
2. 多對多:LiveEventBus.
3.多程序通訊機制
1. 服務提供者向DRouter註冊Action對其他程序暴露服務,傳遞的引數需要實現序列化,否則會被DRouter過濾掉.
2. 多對多:LiveEventBus.
4.資原始檔衝突
1. AndroidManifest.xml合併:
每個module都有一份自己的AndroidManifest清單檔案,在APP的編譯過程中最終會將所有module的清單檔案合併成一份。
我們可以在配置為Application的module下的build/intermediates/manifests路徑下找到合成後的AndroidManifest檔案,對比編譯前後的差異就能大致分析出合併規則和衝突處理規則。
需要注意的是如果在多個module中出現同名資源(如 android:label="@string/app_name"),且同名資源被合成後的AndroidManifest.xml引用,則會優先取用當前ApplicationModule的資源。
2. R檔案:
libModule中R檔案裡的id不再是靜態常量,而是靜態變數,所以不能再使用switch..case..語法操作資源id
3. 其他resource:

2. 關於資源的拆分,一些style、常見的string、共用的圖片、drawable等資源,建議存放在common_service當中。對於屬於不同模組的資源則應該存放在各自的module中。
5.如何配置Module單獨除錯?
第一步:在 工程根目錄 下的gradle.properties下宣告對應module是否獨立執行的屬性,如isDebugMode。因為gradle.properties中申明的屬性在各個module的build.gradle中可以被直接訪問
第二步:在module的build.gradle檔案中加上紅框內的三個部分:
設定module型別:
```
if (isDebugMode.toBoolean()) {
apply plugin: 'com.android.library'
} else {
apply plugin: 'com.android.application'
}
設定applicationId:
if (!isDebugMode.toBoolean()) {
applicationId "com.dovar.router"
}
使用sourceSets配置AndroidManifest等
sourceSets {
main {
if (isDebugMode.toBoolean()) {
manifest.srcFile 'src/debug/AndroidManifest.xml'
} else {
manifest.srcFile 'src/release/AndroidManifest.xml'
}
}
}
```
更好的實現方式應該是這樣的:設定一個可執行的殼工程,如示例中的app.然後在殼工程中配置元件依賴.
6.元件化後的Git部署
一般我們專案只會對應於一個Git倉庫,於是所有開發成員都可以對專案中所有程式碼進行編輯並提交修改,但作為專案管理者,我們想讓成員只能提交自己負責的業務程式碼,避免成員在開發過程中不小心修改了其他成員的程式碼導致出現bug。而通過元件化後,我們就可以根據成員開發職責重新設定程式碼修改許可權啦。
假設:在開發過程中基礎框架層不變,甲負責module_a,乙負責module_b,丙負責module_c和打包,甲乙丙都可以修改common_service。於是我們將module_a/module_b/module_c/common_service全都獨立成子倉庫,module_a倉庫只對甲開放修改許可權,module_b倉庫只對乙開放修改許可權,module_c倉庫只對丙開放修改許可權,於是就有下圖所示的許可權分佈:

有以下三種Git部署方式可供選擇:

如何漸進式的進行元件化改造?
完全的元件化拆分並非一兩日就能完成,而我們的專案卻總會不斷有新的需求等待開發,版本迭代工作幾乎註定了我們不可能將專案需求暫停來做元件化。
那麼,版本迭代與元件化拆分就需要同步進行,下面是我的建議:
1.開始準備:
* 新增APP殼工程,建議參考本專案中的app工程.
* 將你專案當前的application工程作為公共服務層(後面直接用common_service表示),當然,由於還未開始拆分元件,所以此時它也是最大的業務元件.
* 新增一個元件(後面用module_search表示),建議優先選擇一個自己最熟悉或相對簡單的業務模組著手,比如我自己公司專案的搜尋模組,它只有搜尋功能且與其他模組互動很少,所以我選擇由它開始。
2.建立依賴鏈:
殼工程依賴common_service.
殼工程依賴module_search.
module_search依賴common_service.(implementation依賴)
3.引入DRouter:
參考上面的DRouter使用說明.
4.分離公共服務層與基礎架構層(非必須):
如果之前你的專案沒有分離業務層和基礎架構層,那麼建議你現在將基礎架構從common_service中抽離出來.
5.逐步拆分元件:
拆分第一個元件:
* 前面我們已經新增了module_search,所以現在要將搜尋模組的程式碼從common_service中抽離並放入搜尋元件,此時搜尋元件依然可以直接引用公共服務層的程式碼,但公共服務層則只能通過路由使用搜索功能.
* 在開發主線做新需求時,新增的資原始檔建議最好放到對應的元件工程中,之前的資原始檔可以暫時保留在公共服務層,等待後續由各個元件工程認領走,儘可能少的積壓在公共服務層。
* 許可權、Android四大元件、特有的第三方庫引用等都應該宣告在對應的元件Module中,而不應沉入公共服務層,更不允許進入基礎框架層。
拆分第二個元件、第三個...
(在第一個元件拆分成功並推入市場後,如果反饋良好,那麼就可以繼續拆分其他的元件了)
元件拆分粒度取決於你的業務模組劃分和組員開發職責劃分,建議不要拆分出太多的元件。


以上學習方向我們有自己的高清思維方向導圖,架構師有自己講解的架構視訊分享(包括高階UI、效能優化、架構師課程、 NDK、混合式開發:ReactNative+Weex等多個Android技術知識的架構視訊資料和各種電子書籍閱讀),視訊資料獲取方式: 關注+點贊+加群:185873940 免費獲取!