Android Componentization (組件化架構(gòu)) 演變

1.前言

  • 組件化 在Android開(kāi)發(fā)的近幾年來(lái),已經(jīng)由單純編寫(xiě)代碼的概念(工具類(lèi)野芒、第三方組件等等)遷移并應(yīng)用于項(xiàng)目的架構(gòu)上,而在應(yīng)用項(xiàng)目架構(gòu)過(guò)程中又演變出多種不同的實(shí)現(xiàn)方案嘱朽,隨著現(xiàn)代APP應(yīng)用市場(chǎng)的快速發(fā)展栏渺,應(yīng)用開(kāi)發(fā)的時(shí)間、效率凯傲、穩(wěn)定性犬辰、可擴(kuò)展性、靈活性都要體現(xiàn)出高標(biāo)準(zhǔn)的行業(yè)水平冰单,因此開(kāi)發(fā)者就想出把項(xiàng)目劃分多個(gè)模塊幌缝,并且需求滿(mǎn)足協(xié)同與獨(dú)立開(kāi)發(fā),組件化就由此誕生诫欠。
  • 文章中實(shí)例 linhaojian的Github

2.目錄

目錄.png

3.組件化發(fā)展史

  • 項(xiàng)目架構(gòu)發(fā)展過(guò)程中涵卵,包含非常多種實(shí)現(xiàn)方式,我將它們劃分了三種 傳統(tǒng)荒叼、模塊缘厢、組件
    項(xiàng)目架構(gòu)分類(lèi).png

3.1 傳統(tǒng)化項(xiàng)目結(jié)構(gòu)

傳統(tǒng)化結(jié)構(gòu).png
  • 傳統(tǒng)化結(jié)構(gòu):通過(guò) 項(xiàng)目?jī)?nèi)業(yè)務(wù)分包 的方式進(jìn)行開(kāi)發(fā),這種方式 維護(hù)甩挫、擴(kuò)展都非常困難贴硫,并且不方便團(tuán)隊(duì)開(kāi)發(fā),只適應(yīng)小項(xiàng)目伊者。

3.2 模塊化項(xiàng)目結(jié)構(gòu)

模塊化結(jié)構(gòu).png
  • 模塊化結(jié)構(gòu):在AndroidStudio 開(kāi)發(fā)工具內(nèi)英遭,通過(guò) 創(chuàng)建module 的方式進(jìn)行劃分不同的業(yè)務(wù)功能,然后在主項(xiàng)目與module 或者 module間構(gòu)建關(guān)聯(lián)(這種關(guān)聯(lián)方式耦合性高)亦渗,當(dāng)module不合理設(shè)置的適合挖诸,會(huì)出現(xiàn)module之間類(lèi)庫(kù)的冗余或者重復(fù)使用。

3.3 組件化項(xiàng)目結(jié)構(gòu)

組件化結(jié)構(gòu).png
  • 組件化結(jié)構(gòu):組件化就是在模塊化的思想上優(yōu)化演變出來(lái)法精,在模塊化思想上多律,通過(guò)1.抽出module間公用部分;2.使用路由Router解耦module間的交互搂蜓;3.gradle集成與獨(dú)立配置狼荞;4.代碼與資源的隔離,使得module同時(shí)支持集成開(kāi)發(fā)與獨(dú)立開(kāi)發(fā)帮碰。

4.定義

  • 將重復(fù)的代碼進(jìn)行封裝相味,業(yè)務(wù)功能劃分為最小粒子。

5.作用

  • 1.復(fù)用代碼殉挽;
  • 2.降低業(yè)務(wù)功能間的依賴(lài)或者關(guān)聯(lián)丰涉;
  • 3.提供單獨(dú)業(yè)務(wù)運(yùn)行與調(diào)試拓巧;

6.特點(diǎn)

  • 1.module具備獨(dú)立性,可單獨(dú)運(yùn)行或調(diào)試一死;
  • 2.module間高度解耦肛度,通過(guò)路由交互
  • 3.代碼與資源隔離投慈;
  • 4.module劃分盡可能粒子化承耿,便于維護(hù)與復(fù)用

7.組件化架構(gòu)

  • 借助以下的包含實(shí)例的圖逛裤,便于更深入了解 組件化 的架構(gòu)瘩绒;
    組件化分層.png
  • 圖中總共分4層 組件集成、業(yè)務(wù)組件带族、功能組件锁荔、運(yùn)行環(huán)境
    • 組件集成:將所有業(yè)務(wù)組件組合到APP的空殼項(xiàng)目中(空殼項(xiàng)目中只包含啟動(dòng)頁(yè)蝙砌,無(wú)任何業(yè)務(wù)邏輯)阳堕;
    • 業(yè)務(wù)組件:將項(xiàng)目按照功能需要?jiǎng)澐至6容^小的module;
    • 功能組件:將不同業(yè)務(wù)組件中公用部分封裝為各種類(lèi)庫(kù)择克;
    • 運(yùn)行環(huán)境:項(xiàng)目開(kāi)發(fā)中所依賴(lài)的語(yǔ)言庫(kù)或者開(kāi)發(fā)環(huán)境恬总;
  • 從圖中可以發(fā)現(xiàn),組件化只存在 垂直關(guān)系肚邢,使各業(yè)務(wù)功能更獨(dú)立與清晰壹堰,更適合現(xiàn)代團(tuán)隊(duì)開(kāi)發(fā)的要求。

8.組件化實(shí)踐

  • 下面簡(jiǎn)單配合例子實(shí)踐組件化開(kāi)發(fā)過(guò)程骡湖;
    • 項(xiàng)目:類(lèi)似于便利生活的應(yīng)用贱纠;
    • 功能:登錄、注冊(cè)响蕴、酒店谆焊、外賣(mài);
  • 項(xiàng)目結(jié)構(gòu)如下圖:


    例子項(xiàng)目結(jié)構(gòu).png

8.1 base公用

  • 1.將module間公用的代碼封裝base的庫(kù)(如:Log庫(kù)浦夷、Base庫(kù)辖试、網(wǎng)絡(luò)請(qǐng)求庫(kù)等等);
  • 2.在4個(gè)模塊中添加引用劈狐;


    base引用.png

8.2 module獨(dú)立與集成

  • 將4個(gè)配置為可以單獨(dú)運(yùn)行或者集成運(yùn)行的狀態(tài):
    • 1.打開(kāi)各種module中 gradle.properties文件罐孝,添加如下內(nèi)容:
      集成于與獨(dú)立配置1.png
    • 2.打開(kāi)各種module中 build.gradle文件,添加如下內(nèi)容:
      集成于與獨(dú)立配置2.png

      集成于與獨(dú)立配置3.png
    • 3.在module獨(dú)立運(yùn)行時(shí)懈息,需要為其添加對(duì)應(yīng)獨(dú)立運(yùn)行的AndroidManifest.xml文件:


      集成于與獨(dú)立配置4.png
  • 注:可以通過(guò)修改isRunAlone的賦值肾档,就能改變module的運(yùn)行狀態(tài),true:可獨(dú)立運(yùn)行辫继,false:集成運(yùn)行怒见。

8.3 多Application初始化

  • 因?yàn)閙odule已具備獨(dú)立運(yùn)行開(kāi)發(fā)的特點(diǎn),所以開(kāi)發(fā)過(guò)程中module中就會(huì)按照自己功能內(nèi)需求初始化所需的第三方類(lèi)庫(kù)或者工具庫(kù)姑宽,因此module中就會(huì)存在各自的Application類(lèi)遣耍,那么在集成開(kāi)發(fā)過(guò)程中,我們也需要把module內(nèi)的Application進(jìn)行初始化調(diào)用炮车,不然就會(huì)與獨(dú)立開(kāi)發(fā)不兼容的問(wèn)題舵变,可以通過(guò) 反射 解決:

8.3.1 實(shí)現(xiàn)原理

  • 主application 中,通過(guò) 反射 把其他module的Application初始化瘦穆。

8.3.2 實(shí)現(xiàn)過(guò)程

* 1.創(chuàng)建一個(gè)抽象BaseApplication纪隙,其他module都繼承于它。
public abstract class BaseApplication extends Application{
    public abstract void init(Context context);// 1
    @Override
    public void onCreate() {
        super.onCreate();
        // 初始化所有module公用的類(lèi)庫(kù)
        initPublic();
        // 初始化不同module的Application
        init(getApplicationContext());// 2
    }
    /**
     * 初始化Module功能的類(lèi)庫(kù)
     */
    public void initPublic(){
        ARouter.init(this);
    }
}
  • 注釋1:提供抽象init方法扛或,使其他module都在init函數(shù)中進(jìn)行初始化绵咱。
  • 注釋2:統(tǒng)一和兼容集成與獨(dú)立的2種開(kāi)發(fā)環(huán)境
    • 2.讓Login組件繼承BaseApplication
public class LoginAppcation extends BaseApplication {
    @Override
    public void init(Context context) {
        //初始化 login組件 中使用的類(lèi)庫(kù)
        // dagger2 、rxjava ....
    }
}
* 3.在主項(xiàng)目或者main組件中熙兔,通過(guò)反射進(jìn)行初始化
public class MainAppcation extends BaseApplication {
    //module中application類(lèi)的路徑
    private static final String[] MODULESLIST =
            {"com.lhj.component.login.LoginAppcation"};
    @Override
    public void init(Context context) {
        //初始化 main組件 中所需的類(lèi)庫(kù)
        // 初始化其他module的Application
        modulesApplicationInit(context);
    }
    /**
     * 通過(guò)反射的方式悲伶,獲取指定Application類(lèi)的實(shí)例,并調(diào)用init函數(shù),解決組件化多appplication獨(dú)立的問(wèn)題
     */
    private void modulesApplicationInit(Context context){
        for (String moduleImpl : MODULESLIST){
            try {
                Class<?> clazz = Class.forName(moduleImpl);
                Object obj = clazz.newInstance();
                if (obj instanceof BaseApplication){
                    ((BaseApplication) obj).init(context);
                }
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InstantiationException e) {
                e.printStackTrace();
            }
        }
    }
}
  • 通過(guò) 反射 很好的解決組件獨(dú)立開(kāi)發(fā)的多個(gè)Application初始化問(wèn)題住涉,并且同時(shí)兼容集成開(kāi)發(fā)環(huán)境麸锉,但是反射就存在性能的問(wèn)題,但暫時(shí)沒(méi)有想到一個(gè)更好的解決方案舆声,請(qǐng)各位大神可以評(píng)論指教花沉。

8.4 module間界面的跳轉(zhuǎn)

8.5 代碼隔離

  • 在集成開(kāi)發(fā)中毙芜,主項(xiàng)目需要對(duì)4個(gè)模塊進(jìn)行引用忽媒,但為了防止在主項(xiàng)目編譯時(shí)引用了其他module內(nèi)的類(lèi)的問(wèn)題,所以需要實(shí)現(xiàn)代碼隔離腋粥,使得真正意義上獨(dú)立晦雨。
  • 可以在引用module時(shí),使用以下方式:


    代碼隔離.png

8.6 資源隔離

  • 在集成開(kāi)發(fā)中隘冲,如果module之間存在資源名字相同的情況時(shí)闹瞧,可能會(huì)影響項(xiàng)目的運(yùn)行或者誤導(dǎo)開(kāi)發(fā)人員,
    所以建議為不同module的資源文件添加對(duì)應(yīng)的命名規(guī)則
    • 1.xml內(nèi)(string展辞、colors等資源文件)的命名方式可以通過(guò)如下配置方式奥邮;
  • 如:將登錄module的xml文件
android {
    //...
    // 實(shí)現(xiàn)資源隔離
    resourcePrefix "login_"
}
* 2. 對(duì)于控件名稱(chēng)與文件名稱(chēng),可根據(jù)自己的喜歡區(qū)分;

8.7 數(shù)據(jù)復(fù)用

  • 項(xiàng)目開(kāi)發(fā)過(guò)程中洽腺,經(jīng)常會(huì)出現(xiàn)數(shù)據(jù)需要全局應(yīng)用脚粟,因此在多module間需要實(shí)現(xiàn)數(shù)據(jù)復(fù)用,可以通過(guò)以下方式實(shí)現(xiàn):
    • 1.使用Arouter框架中的Provider功能(將復(fù)用的數(shù)據(jù)保存base庫(kù)的Provider中蘸朋,然后通過(guò)Arouter的navigation函數(shù)獲群宋蕖);
    • 2.base庫(kù)中藕坯,可以按需添加對(duì)象全局?jǐn)?shù)據(jù)的管理類(lèi)团南。

8.8 資源復(fù)用

  • 將可能會(huì)復(fù)用的資源,添加至base庫(kù)中炼彪,防止資源重復(fù)的問(wèn)題吐根。

9.總結(jié)

  • 到此,Android項(xiàng)目組件化開(kāi)發(fā)介紹完畢辐马!
  • 如果喜歡我的分享拷橘,可以點(diǎn)擊 關(guān)注 或者 ,你們支持是我分享的最大動(dòng)力 齐疙。
  • linhaojian的Github

歡迎關(guān)注linhaojian_CSDN博客或者linhaojian_簡(jiǎn)書(shū)膜楷!

不定期分享關(guān)于安卓開(kāi)發(fā)的干貨。


寫(xiě)技術(shù)文章初心

  • 技術(shù)知識(shí)積累
  • 技術(shù)知識(shí)鞏固
  • 技術(shù)知識(shí)分享
  • 技術(shù)知識(shí)交流
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末贞奋,一起剝皮案震驚了整個(gè)濱河市赌厅,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌轿塔,老刑警劉巖特愿,帶你破解...
    沈念sama閱讀 222,590評(píng)論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異勾缭,居然都是意外死亡揍障,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,157評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)俩由,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)毒嫡,“玉大人,你說(shuō)我怎么就攤上這事幻梯《祷” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 169,301評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵碘梢,是天一觀的道長(zhǎng)咬摇。 經(jīng)常有香客問(wèn)我,道長(zhǎng)煞躬,這世上最難降的妖魔是什么肛鹏? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 60,078評(píng)論 1 300
  • 正文 為了忘掉前任逸邦,我火速辦了婚禮,結(jié)果婚禮上在扰,老公的妹妹穿的比我還像新娘缕减。我一直安慰自己,他們只是感情好健田,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,082評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布烛卧。 她就那樣靜靜地躺著佛纫,像睡著了一般妓局。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上呈宇,一...
    開(kāi)封第一講書(shū)人閱讀 52,682評(píng)論 1 312
  • 那天好爬,我揣著相機(jī)與錄音,去河邊找鬼甥啄。 笑死存炮,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的蜈漓。 我是一名探鬼主播穆桂,決...
    沈念sama閱讀 41,155評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼融虽!你這毒婦竟也來(lái)了享完?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 40,098評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤有额,失蹤者是張志新(化名)和其女友劉穎般又,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體巍佑,經(jīng)...
    沈念sama閱讀 46,638評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡茴迁,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,701評(píng)論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了萤衰。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片堕义。...
    茶點(diǎn)故事閱讀 40,852評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖脆栋,靈堂內(nèi)的尸體忽然破棺而出倦卖,到底是詐尸還是另有隱情,我是刑警寧澤筹吐,帶...
    沈念sama閱讀 36,520評(píng)論 5 351
  • 正文 年R本政府宣布糖耸,位于F島的核電站,受9級(jí)特大地震影響丘薛,放射性物質(zhì)發(fā)生泄漏嘉竟。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,181評(píng)論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望舍扰。 院中可真熱鬧倦蚪,春花似錦、人聲如沸边苹。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,674評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)个束。三九已至慕购,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間茬底,已是汗流浹背沪悲。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,788評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留阱表,地道東北人殿如。 一個(gè)月前我還...
    沈念sama閱讀 49,279評(píng)論 3 379
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像最爬,于是被迫代替她去往敵國(guó)和親涉馁。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,851評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容