Android應(yīng)用架構(gòu)前世今生

前言

Android的開發(fā)生態(tài)系統(tǒng)發(fā)展迅速茵汰,在開發(fā)Android的幾年的時(shí)間里,用來構(gòu)建Android應(yīng)用的架構(gòu)與技術(shù)一直在不斷進(jìn)化产阱。隨著項(xiàng)目的不斷更新迭代渠退,應(yīng)用的架構(gòu)也有不一樣的變化。由于開發(fā)人員的數(shù)量设预、項(xiàng)目的業(yè)務(wù)復(fù)雜度徙歼、需求的開發(fā)時(shí)間、應(yīng)用的使用量級(jí)絮缅,使用的技術(shù)架構(gòu)也不相同鲁沥。沒有最好的架構(gòu),只有最合適的耕魄。通過設(shè)計(jì)使程序模塊化画恰,做到模塊內(nèi)部的高聚合和模塊之間的低耦合。這樣做的好處是使得程序在開發(fā)的過程中吸奴,開發(fā)人員只需要專注于一點(diǎn)允扇,提高程序開發(fā)的效率缠局,便于項(xiàng)目的后期維護(hù)。下面總結(jié)及匯總一下目前Android使用的主要應(yīng)用架構(gòu)及其優(yōu)缺點(diǎn)和使用的學(xué)習(xí)心得考润,如有不對(duì)之處狭园,歡迎交流糾正。

mvc

還記得以前學(xué)生時(shí)代學(xué)習(xí).NET的時(shí)候糊治,第一次接觸到項(xiàng)目架構(gòu)叫三層架構(gòu)唱矛。應(yīng)用層、業(yè)務(wù)邏輯層及數(shù)據(jù)訪問層井辜。mvc的思想其實(shí)也一樣绎谦,都是一種軟件設(shè)計(jì)典范,用一種業(yè)務(wù)邏輯粥脚、數(shù)據(jù)窃肠、界面顯示分離的方法組織代碼,在改進(jìn)和個(gè)性化定制界面及用戶交互的同時(shí)刷允,不需要重新編寫業(yè)務(wù)邏輯冤留。Android的項(xiàng)目設(shè)計(jì)本身也是采用了mvc的設(shè)計(jì)思想。

115截圖20180108120929.png
  • 視圖層(View)
    一般采用XML文件進(jìn)行界面的描述树灶,使用的時(shí)候可以非常方便的引入纤怒。同時(shí)便于后期界面的修改。邏輯中與界面對(duì)應(yīng)的id不變化則代碼不用修改天通,大大增強(qiáng)了代碼的可維護(hù)性肪跋。

  • 控制層(Controller)
    Android的控制層主要就是Activity層。相關(guān)View層交互觸發(fā)及數(shù)據(jù)展示邏輯都在Activity中進(jìn)行編碼土砂。

  • 模型層(Model)

我們通常針對(duì)業(yè)務(wù)數(shù)據(jù)州既,都會(huì)定義好對(duì)應(yīng)的Model層。數(shù)據(jù)庫的操作萝映、對(duì)網(wǎng)絡(luò)等的操作都應(yīng)該在Model里面處理吴叶,當(dāng)然對(duì)業(yè)務(wù)計(jì)算等操作也是必須放在的該層的

所以一直以來我們使用Android默認(rèn)的項(xiàng)目結(jié)構(gòu)開發(fā),主要都是在采用mvc的架構(gòu)思想序臂。

優(yōu)點(diǎn): 適用了簡單的頁面展示蚌卤,業(yè)務(wù)邏輯不復(fù)雜。開發(fā)效果高奥秆,代碼層級(jí)也簡單易懂

缺點(diǎn): 當(dāng)業(yè)務(wù)復(fù)雜時(shí)逊彭,Activity非常臃腫,不便于維護(hù)及測試

mvp

mvp這是目前我們項(xiàng)目中主要采用的應(yīng)用架構(gòu)方式构订,MVP從更早的MVC框架演變過來侮叮,與MVC有一定的相似性:Controller/Presenter負(fù)責(zé)邏輯的處理,Model提供數(shù)據(jù)悼瘾,View負(fù)責(zé)顯示囊榜。mvp架構(gòu)的演變审胸,解決了Activity代碼臃腫的問題,當(dāng)我們將Activity復(fù)雜的邏輯處理移至另外的一個(gè)類(Presenter)中時(shí)卸勺,Activity其實(shí)就是MVP模式中的View砂沛,它負(fù)責(zé)UI元素的初始化,建立UI元素與Presenter的關(guān)聯(lián)(Listener之類)曙求,同時(shí)自己也會(huì)處理一些簡單的邏輯(復(fù)雜的邏輯交由 Presenter處理)碍庵。項(xiàng)目開發(fā)中,UI是容易變化的悟狱,且是多樣的怎抛,一樣的數(shù)據(jù)會(huì)有N種顯示方式;業(yè)務(wù)邏輯也是比較容易變化的芽淡。為了使得應(yīng)用具有較大的彈性,我們期望將UI豆赏、邏輯(UI的邏輯和業(yè)務(wù)邏輯)和數(shù)據(jù)隔離開來挣菲,而MVP是一個(gè)很好的選擇。在MVP模式里通常包含3個(gè)要素(加上View interface是4個(gè)):

115截圖20180108122650.png
  • View:負(fù)責(zé)繪制UI元素掷邦、與用戶進(jìn)行交互(在Android中體現(xiàn)為Activity)

  • Model:負(fù)責(zé)存儲(chǔ)白胀、檢索、操縱數(shù)據(jù)(有時(shí)也實(shí)現(xiàn)一個(gè)Model interface用來降低耦合)

  • Presenter:作為View與Model交互的中間紐帶抚岗,處理與用戶交互的負(fù)責(zé)邏輯或杠。

  • View interface:需要View實(shí)現(xiàn)的接口,View通過View interface與Presenter進(jìn)行交互宣蔚,降低耦合向抢,方便進(jìn)行單元測試

優(yōu)點(diǎn):

  1. Model與View完全分離,修改互不影響
  2. 更高效地使用胚委,因?yàn)樗械倪壿嫿换ザ及l(fā)生在一個(gè)地方—Presenter內(nèi)部
  3. 一個(gè)Preseter可用于多個(gè)View挟鸠,而不需要改變Presenter的邏輯(因?yàn)閂iew的變化總是比Model的變化頻繁)。
  4. 更便于測試亩冬。把邏輯放在Presenter中艘希,就可以脫離用戶接口來測試邏輯(單元測試)

缺點(diǎn): 需要拿捏好Presenter、View interface的顆粒度設(shè)計(jì)硅急,容易出現(xiàn)Presenter過于簡單或則復(fù)雜化覆享。

mvvm

MVVM可以算是MVP的升級(jí)版,其中的VM是ViewModel的縮寫营袜,ViewModel可以理解成是View的數(shù)據(jù)模型和Presenter的合體撒顿,ViewModel和View之間的交互通過Data Binding完成,而Data Binding可以實(shí)現(xiàn)雙向的交互荚板,這就使得視圖和控制層之間的耦合程度進(jìn)一步降低核蘸,關(guān)注點(diǎn)分離更為徹底巍糯,同時(shí)減輕了Activity的壓力

115截圖20180108140536.png
  • View(視圖層)采用XML文件進(jìn)行界面的描述;
  • Model(模型層)通過網(wǎng)絡(luò)和本地?cái)?shù)據(jù)庫獲取視圖層所需數(shù)據(jù)客扎;
  • ViewModel(視圖-模型層)負(fù)責(zé)View和Model之間的通信祟峦,以此分離視圖和數(shù)據(jù)。

View和Model之間通過Android Data Binding技術(shù)徙鱼,實(shí)現(xiàn)視圖和數(shù)據(jù)的雙向綁定宅楞;ViewModel持有Model的引用,通過Model的方法請(qǐng)求數(shù)據(jù)袱吆;獲取數(shù)據(jù)后厌衙,通過Callback(回調(diào))的方式回到ViewModel中,由于ViewModel與View的雙向綁定绞绒,使得界面得以實(shí)時(shí)更新婶希。同時(shí),界面輸入的數(shù)據(jù)變化時(shí)蓬衡,由于雙向綁定技術(shù)喻杈,ViewModel中的數(shù)據(jù)得以實(shí)時(shí)更新,提高了數(shù)據(jù)采集的效率狰晚。

采用ViewModel解決MVP中View(Activity)和Presenter相互持有對(duì)方應(yīng)用的問題筒饰,界面由數(shù)據(jù)進(jìn)行驅(qū)動(dòng),響應(yīng)界面操作無需由View(Activity)傳遞壁晒,數(shù)據(jù)的變化也無需Presenter調(diào)用View(Activity)實(shí)現(xiàn)瓷们,使得數(shù)據(jù)傳遞的過程更加簡潔,高效秒咐。

推薦教程:
精通 Android Data Binding

優(yōu)點(diǎn):

  1. 雙向綁定技術(shù)谬晕,當(dāng)Model變化時(shí),View-Model會(huì)自動(dòng)更新携取,View也會(huì)自動(dòng)變化固蚤。很好做到數(shù)據(jù)的一致性
  2. Google官方支持databing,易于集成

缺點(diǎn):

  1. 數(shù)據(jù)綁定使得 Bug 很難被調(diào)試
  2. 數(shù)據(jù)雙向綁定不利于代碼重用及擴(kuò)展
  3. 代碼的閱讀性降低

android-architecture

google在官方示例中給出了一系列不同架構(gòu)的app實(shí)現(xiàn)歹茶,項(xiàng)目目的是通過展示各種架構(gòu)app的不同方式來幫助開發(fā)者解決架構(gòu)問題夕玩。項(xiàng)目中通過不同的架構(gòu)概念及方式實(shí)現(xiàn)了功能相同的app。

Google官方MVP架構(gòu)示例項(xiàng)目

TODO-MVP-RXJAVA

115圖片20180108151621.png

使用RXJAVA對(duì)數(shù)據(jù)流進(jìn)行處理惊豺,并且通過Repository進(jìn)行數(shù)據(jù)的集中管理燎孟,通過協(xié)議類XXXContract來對(duì)View和Presenter的接口進(jìn)行內(nèi)部繼承,在presenter的實(shí)現(xiàn)類中尸昧,可以對(duì)Model數(shù)據(jù)進(jìn)行操作揩页。實(shí)例中,數(shù)據(jù)的獲取烹俗、存儲(chǔ)爆侣、數(shù)據(jù)狀態(tài)變化都是model層的任務(wù)萍程,presenter會(huì)根據(jù)需要調(diào)用該層的數(shù)據(jù)處理邏輯并在需要時(shí)將回調(diào)傳入。這樣model兔仰、presenter茫负、view都只處理各自的任務(wù),實(shí)現(xiàn)單一責(zé)任原則乎赴。

推薦教程:
Google官方MVP+Rxjava項(xiàng)目詳解

組件化

隨著項(xiàng)目的推進(jìn)忍法,及企業(yè)業(yè)務(wù)的發(fā)展。有一天可以發(fā)現(xiàn)團(tuán)隊(duì)內(nèi)部需要開發(fā)多個(gè)APP榕吼,且多個(gè)APP中存在相同的業(yè)務(wù)模塊饿序,一開始的做法為了趕項(xiàng)目進(jìn)度可能就是黏貼復(fù)制,到后面就慢慢發(fā)現(xiàn)越來越吃力羹蚣,重復(fù)勞動(dòng)原探。
慢慢隨著時(shí)間的推移,惡性循環(huán)顽素。慢慢發(fā)現(xiàn)項(xiàng)目代碼結(jié)構(gòu)混亂咽弦、層次不清,各業(yè)務(wù)技術(shù)方案不統(tǒng)一戈抄;甚至連基本的包結(jié)構(gòu)也是胡亂不堪,都是不停地往上堆砌代碼添加新功能后专,前人挖坑后人填划鸽。可見組件化對(duì)于不斷迭代的項(xiàng)目有著深遠(yuǎn)的意義

  1. 避免重復(fù)造輪子戚哎,提高開發(fā)效率
  2. 減低耦合度裸诽,提高復(fù)用性
  3. 保持團(tuán)隊(duì)的技術(shù)方案統(tǒng)一性
  4. 便于維護(hù)升級(jí)

基礎(chǔ)組件化

通常項(xiàng)目中常用的結(jié)構(gòu)如下:

115截圖20180108161144.png

看似沒什么問題,但通常我們的一些庫都是以代碼的形式集成在代碼中型凳,隨著項(xiàng)目推進(jìn)丈冬,慢慢發(fā)現(xiàn)一些比較嚴(yán)重的問題。

  1. 業(yè)務(wù)代碼侵入組件代碼中 (例如一些全局的網(wǎng)絡(luò)返回響應(yīng)甘畅,直接在庫中編碼等)
  2. 團(tuán)隊(duì)內(nèi)部沒約束埂蕊,各自集成不同的基礎(chǔ)庫(例如圖片加載有的用Glide,有的用ImageLoader)
  3. 部分第三方組件停止更新疏唾,項(xiàng)目代碼耦合高蓄氧,替換新方案難

所以在實(shí)際設(shè)施組件化的過程中,建議參考:

  1. 獨(dú)立library庫(Common基礎(chǔ)組件)槐脏,避免在主工程中直接以代碼集成喉童,使用aar方式引用
  2. 第三方的庫調(diào)用最好再裝一層接口,以便后續(xù)維護(hù)升級(jí)
  3. 有成員專門負(fù)責(zé)維護(hù)顿天,可以以SDK的方式提供業(yè)務(wù)層的調(diào)用

業(yè)務(wù)模塊化

隨著項(xiàng)目邏輯不斷的增加堂氯,慢慢是不是發(fā)現(xiàn)代碼編譯速度是不是越來越慢蔑担?(PS:我們目前項(xiàng)目編譯一次2分鐘,且已是經(jīng)過一些優(yōu)化處理)
另外當(dāng)團(tuán)隊(duì)內(nèi)部有多個(gè)項(xiàng)目時(shí)咽白,是不是經(jīng)歷過產(chǎn)品經(jīng)理讓你把項(xiàng)目A的某個(gè)功能移到項(xiàng)目B去啤握,這個(gè)時(shí)候... ...

115截圖20180108163926.png

業(yè)務(wù)模塊化的作用性就很明顯了

  1. 業(yè)務(wù)模塊間避免耦合,提高復(fù)用性
  2. 業(yè)務(wù)模塊獨(dú)立編譯運(yùn)行

推薦教程:
DDComponentForAndroid
Android徹底組件化方案實(shí)踐

總結(jié)

思考

  1. 項(xiàng)目架構(gòu)都是不斷演進(jìn)局扶,不是一蹴而就
  2. 沒有最好的架構(gòu)恨统,只有在適當(dāng)?shù)臅r(shí)機(jī),最合適的架構(gòu)
  3. 項(xiàng)目重構(gòu)過程是艱難的三妈,但長痛不如短痛

推薦業(yè)內(nèi)架構(gòu)演變

安居客Android項(xiàng)目架構(gòu)演進(jìn)

餓了么移動(dòng)APP的架構(gòu)演進(jìn)

微信Android客戶端架構(gòu)演進(jìn)之路

參考資料

Android App的設(shè)計(jì)架構(gòu):MVC,MVP,MVVM與架構(gòu)經(jīng)驗(yàn)談

Android 開發(fā):由模塊化到組件化(一)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末畜埋,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子畴蒲,更是在濱河造成了極大的恐慌悠鞍,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,884評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件模燥,死亡現(xiàn)場離奇詭異咖祭,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)蔫骂,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,755評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門么翰,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人辽旋,你說我怎么就攤上這事浩嫌。” “怎么了补胚?”我有些...
    開封第一講書人閱讀 158,369評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵码耐,是天一觀的道長。 經(jīng)常有香客問我溶其,道長骚腥,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,799評(píng)論 1 285
  • 正文 為了忘掉前任瓶逃,我火速辦了婚禮束铭,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘厢绝。我一直安慰自己纯露,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,910評(píng)論 6 386
  • 文/花漫 我一把揭開白布代芜。 她就那樣靜靜地躺著埠褪,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上钞速,一...
    開封第一講書人閱讀 50,096評(píng)論 1 291
  • 那天贷掖,我揣著相機(jī)與錄音,去河邊找鬼渴语。 笑死苹威,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的驾凶。 我是一名探鬼主播牙甫,決...
    沈念sama閱讀 39,159評(píng)論 3 411
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼调违!你這毒婦竟也來了窟哺?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,917評(píng)論 0 268
  • 序言:老撾萬榮一對(duì)情侶失蹤技肩,失蹤者是張志新(化名)和其女友劉穎且轨,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體虚婿,經(jīng)...
    沈念sama閱讀 44,360評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡旋奢,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,673評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了然痊。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片至朗。...
    茶點(diǎn)故事閱讀 38,814評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖剧浸,靈堂內(nèi)的尸體忽然破棺而出锹引,到底是詐尸還是另有隱情,我是刑警寧澤辛蚊,帶...
    沈念sama閱讀 34,509評(píng)論 4 334
  • 正文 年R本政府宣布粤蝎,位于F島的核電站真仲,受9級(jí)特大地震影響袋马,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜秸应,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,156評(píng)論 3 317
  • 文/蒙蒙 一虑凛、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧软啼,春花似錦桑谍、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,882評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春雹仿,著一層夾襖步出監(jiān)牢的瞬間增热,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,123評(píng)論 1 267
  • 我被黑心中介騙來泰國打工胧辽, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留峻仇,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,641評(píng)論 2 362
  • 正文 我出身青樓邑商,卻偏偏與公主長得像摄咆,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子人断,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,728評(píng)論 2 351

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