Android 組件化案例

為什么組件化
隨著移動(dòng)互聯(lián)網(wǎng)的發(fā)展,或許中小型項(xiàng)目還可以用單工程+MVC/MVP/MVVM的架構(gòu)來(lái)完成,但當(dāng)項(xiàng)目到了一定程度之后,編譯時(shí)間 原來(lái)越長(zhǎng),測(cè)試或者開(kāi)發(fā)任何一個(gè)模塊功能都需要整個(gè)項(xiàng)目重啟運(yùn)行。

常規(guī)單工程+MVC/MVP/MVVM項(xiàng)目:

乍一看,這樣的結(jié)構(gòu)只要咱們模塊分層明確,是不存在大問(wèn)題的,但是隨著業(yè)務(wù)的快速迭代,面臨以下問(wèn)題:

1.需求瘋狂變化,上周剛討論出一套方案,你花了兩天搞定,這個(gè)時(shí)候PM告訴你,這個(gè)咱們修改或者不要了,是否想抓狂呢。

2.所有業(yè)務(wù)都在一個(gè)項(xiàng)目,不管基于什么原因,有時(shí)候咱們?yōu)榱丝焖偻瓿梢粋€(gè)功能,或多或少存在耦合,任何改動(dòng)都可能顯的比較吃力,解決了一個(gè)BUG又出現(xiàn)另外一個(gè)BUG。

3.團(tuán)隊(duì)人數(shù)達(dá)到一定程度后,并行開(kāi)發(fā)過(guò)程中,如果某個(gè)成員不小心犯錯(cuò)并且提交了代碼,可能導(dǎo)致項(xiàng)目暫時(shí)無(wú)法運(yùn)行,不得不停下來(lái)協(xié)同查找問(wèn)題,嚴(yán)重影響開(kāi)發(fā)效率

4.業(yè)務(wù)越來(lái)越多,項(xiàng)目越來(lái)越大,編譯運(yùn)行一次要10秒…20秒…1分鐘…5分鐘…累計(jì)幾個(gè)月下來(lái)的時(shí)間說(shuō)不得抽出來(lái)都可以去找個(gè)女朋友了…

基于以上問(wèn)題,咱們的組件化應(yīng)運(yùn)而生。

組件化結(jié)構(gòu)圖

對(duì)比上張圖,這里的APP主要由業(yè)務(wù)組件構(gòu)成,嚴(yán)格來(lái)說(shuō)這5個(gè)業(yè)務(wù)組件也可以是5個(gè)App,當(dāng)實(shí)現(xiàn)以上架構(gòu)圖,看看組件化的優(yōu)缺點(diǎn):

組件化優(yōu)點(diǎn)

  • 業(yè)務(wù)組件可以單獨(dú)分配并行開(kāi)發(fā)

  • 單個(gè)組件業(yè)務(wù)可以由開(kāi)發(fā)者自行決定采取MVC/MVP/MVVM架構(gòu)而不影響整體大局

  • 新人接手項(xiàng)目分配任務(wù)可單獨(dú)分配某一個(gè)模塊任務(wù),不必關(guān)心整個(gè)項(xiàng)目

  • 開(kāi)發(fā)效率提升,開(kāi)發(fā)過(guò)程僅僅需要維護(hù)開(kāi)發(fā)自己的組件內(nèi)容

  • 若公司有多個(gè)團(tuán)隊(duì),優(yōu)秀代碼組件可快速移植復(fù)用

  • 積累個(gè)人的組件倉(cāng)庫(kù),擺脫粘貼復(fù)制的“搬磚工”身份

  • 測(cè)試可單獨(dú)測(cè)試某個(gè)模塊

組件化的坑

  • 組件與組件之間的調(diào)用,數(shù)據(jù)等交互

  • 多個(gè)組件,在使用application的時(shí)候怎辦

  • 多個(gè)組件資源命名重復(fù)

  • 多個(gè)組件引用不同版本的相同的庫(kù)

了解了優(yōu)缺點(diǎn),咱們進(jìn)入正式的組件化開(kāi)發(fā)集成,后續(xù)將會(huì)描述如何解決組件化的一些坑。

前文說(shuō)過(guò),咱們的5個(gè)組件可以理解為5個(gè)app,下面開(kāi)始集成。


先看看咱們的組件化效果,手機(jī)展示效果,


1:首先統(tǒng)一組件之間的版本以及第三方庫(kù)版本
利用Gradle統(tǒng)一版本號(hào),可參考 android使用Gradle統(tǒng)一配置依賴(lài)版本

2:咱們的組件又是Lib,又是application,如何控制調(diào)試,如何在主APP選擇

在config.build處新增一個(gè)布爾isBuildApp作為標(biāo)志判斷依賴(lài),true表示作為application存在,false表示lib存在

ext {
    isBuildApp=false;//false:作為L(zhǎng)ib組件存在, true:作為application存在
    ...
}

在每個(gè)組件的build根據(jù)isBuildApp來(lái)選擇依賴(lài)

if(rootProject.ext.isBuildApp){
    apply plugin: "com.android.application"
}else{
    apply plugin: 'com.android.library'

}
android{
...
 defaultConfig {
        if(rootProject.ext.isBuildApp){
            applicationId "com.allure.shop"
        }
        ...
    }
}

ibrary與application運(yùn)行時(shí)需要manifest,依然根據(jù)isBuildApp判斷

   sourceSets {
        main {
            if (rootProject.ext.isBuildApp) {
                manifest.srcFile 'src/main/debug/AndroidManifest.xml'
            } else {
                manifest.srcFile 'src/main/release/AndroidManifest.xml'
                java {
                    exclude 'debug/**'
                }
            }
        }
    }

資源的命名為了避免重復(fù),建議按照組件名開(kāi)頭,如Login組件,命名login_xxx,BaiDuMap組件命bd_map_xxx
可用gradle進(jìn)行強(qiáng)制檢測(cè)

resourcePrefix "login_"

主項(xiàng)目的引用

 if (rootProject.ext.isBuildApp) {
        compile project(':modulebase')
    } else {
        compile project(':modulecore:moduleLogin')
        compile project(':modulecore:moduleShop')
    }

解決組件與組件的交互:
方案1:可采用建立中間件的方式來(lái)統(tǒng)一管理組件之間的交互,如電影組件與首頁(yè)組件需要跳轉(zhuǎn)傳值等可采用開(kāi)源的ActivityRouter,EventBus來(lái)完成

方案2:在主項(xiàng)目APP建立統(tǒng)一的入口類(lèi),針對(duì)組件與組件的交互建立方法,實(shí)現(xiàn)接口等,但此方式有一定溝通成本,組件與組件之間的交互維護(hù)可能需要一份文檔來(lái)約束。

application的使用:
方案1:統(tǒng)一使用基礎(chǔ)庫(kù)的單例BaseApplication
方案2:反射ActivityThread

Lib與Application的切換
修改config.build里的isBuildApp屬性并且重新sync

項(xiàng)目結(jié)構(gòu)圖:
作為組件Lib

作為單獨(dú)的application

總結(jié)

組件化技術(shù)難度不大,難點(diǎn)在于業(yè)務(wù)的解耦。具體是否選擇組件化方式還是要根據(jù)項(xiàng)目大小來(lái)確定。 當(dāng)然采取了組件化是極好的。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容