一、項目演進
混沌項目 -> 模塊化 -> 組件化
- 混沌項目:所有代碼在一個主工程中,僅僅做了分包。
- 模塊化:項目按業(yè)務拆分多個module,但是各module之間耦合嚴重。
- 組件化:對模塊化的module進一步分層,根據分層確定依賴規(guī)則,優(yōu)化模塊化混亂耦合的局面,使各模塊間相對獨立。
二、組件化描述
2.1 組件形式:
- module 工程模塊
- project 獨立項目
2.2 分層:
- business 具體業(yè)務
- sdk 通用業(yè)務能力
- lib 通用庫能力
- base 基礎庫能力
視業(yè)務復雜度看是否在business和sdk之間抽個loft層,作為通用業(yè)務封裝和通信輔助層。
2.3 組件化優(yōu)勢:
- 模塊獨立:提升編譯速度、提高開發(fā)效率、降低維護成本、提升測試效率。
- 拓展性好:方便組件的新增和刪除,也為項目內部組件的插件化提供環(huán)境。
2.4 組件化要解決的問題:
- 獨立調試
- 解耦
- 解耦之后組件間的跳轉與通信
三、組件化實踐
結合自己的工作,來簡單整理下項目組件化實踐。
3.1 獨立調試
獨立project肯定不需要考慮調試問題,這里主要是指module的組件形式。需要獨立編譯的module:gradle中 apply plugin: ‘com.android.library’ 改為apply plugin: ‘com.android.application',另外需要配置一個能啟動系統(tǒng)組件的AndroidMainfest.xml。為了方便修改,可以在gradle.properties配置開關來切換調試模式。
示例:
動態(tài)配置組件類型、ApplicationId和AndroidManifest
//gradle.properties 配置統(tǒng)一調試開關
isModule = false
//build.gradle
if (isModule.toBoolean()){
apply plugin: 'com.android.application'
}else {
apply plugin: 'com.android.library'
}
//build.gradle (XX module)
android {
...
defaultConfig {
...
if (isModule.toBoolean()) {
// 獨立調試時添加 applicationId ,集成調試時移除
applicationId "包名"
}
...
}
sourceSets {
main {
// 獨立調試與集成調試時使用不同的 AndroidManifest.xml 文件
if (isModule.toBoolean()) {
manifest.srcFile 'src/main/moduleManifest/AndroidManifest.xml'
} else {
manifest.srcFile 'src/main/AndroidManifest.xml'
}
}
}
...
}
3.2 解耦
解耦主要就是組件分層,上級可以依賴下級但不跨級依賴,平級之間不互相依賴, 通用功能需要提取則在兩層之間抽取loft層,一般來說business可能會抽取通用業(yè)務組件作為loft。

1)基礎能力庫
主要提供整個項目通用的工具、Base頁面等等,它自身無任何依賴,因此放在base層。通用型sdk和lib不依賴于Base-Core,方便托管maven成為獨立庫。
2)網絡庫(Okhttp)
多個終端項目,下沉一個通用的Base-Network,滿足基礎網絡請求能力,包括:通用請求配置設置、通用請求參數封裝、通用響應數據解析等的支持。Lib層梳理出差異化的Lib-Network,主要包括通用業(yè)務請求類型封裝、網絡請求加密策略(不同終端有差異因此放到lib層)等。Base-Network自身可以托管maven。
3)圖片庫(Glide)、插件化庫(RePlugin)、熱修復庫(Tinker)
這仨算一個類型,放一塊說。Glide自身默認使用HttpURLConnection作為網絡獲取圖片方案,這里直接可以使用Base-Network來統(tǒng)一提供網絡請求能力。而插件化庫、熱修復庫這兩個框架因為都需要下發(fā)插件,所以也可以統(tǒng)一依賴Base-Network。真實場景是:圖片庫、插件化庫、熱修復庫都會作為maven托管,提供終端通用能力,如果各自維護一套網絡請求方案顯然還是不合理。
4)播放框架
播放框架做了一次大的重構,將之前冗雜的播控功能進行組件化拆分:
- Lib-CorePlayer:支持播放的系統(tǒng)庫和三方庫。向上統(tǒng)一提供基礎播放能力。
- Sdk-PlayerFramework: 播控中心,封裝view的基礎控制功能以及封裝player的基礎播放功能
- Loft-Live 、Loft-Vod:分別封裝直播和點播兩大通用業(yè)務。分別實現對應的播控,以及個性化能力。因為是通用型業(yè)務,因此這里增加了個Loft層,理解為common business。
3.3 跳轉
通過組件分層與依賴限制最大程度已經實現了組件解耦,那接下的問題是,不相互依賴的組件間如何進行跳轉和通信 ?
1)Intent隱式跳轉
- action跳轉
<intent-filter>
<action android:name=“XXX" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
intent.setAction(action);
startActivity(intent);
- uri跳轉
<intent-filter>
<action android:name=“XXX" />
<category android:name="android.intent.category.DEFAULT" />
<data
android:host="channel"
android:path="/channel_page"
android:scheme=“XXX"></data>
</intent-filter>
intent.setData(Uri.parse(scheme + "://" + host + path));
startActivity(intent);
2)路由 Arouter
3.4 通信
如果組件化分層足夠合理的話,需要互相通信的組件大部分都處于上面的業(yè)務層,通信方式:或通過Loft層建立依賴關系來注冊觀察者,或實在不行就發(fā)本地廣播。