前言
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ì)思想。
視圖層(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è)):
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):
- Model與View完全分離,修改互不影響
- 更高效地使用胚委,因?yàn)樗械倪壿嫿换ザ及l(fā)生在一個(gè)地方—Presenter內(nèi)部
- 一個(gè)Preseter可用于多個(gè)View挟鸠,而不需要改變Presenter的邏輯(因?yàn)閂iew的變化總是比Model的變化頻繁)。
- 更便于測試亩冬。把邏輯放在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的壓力
- 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):
- 雙向綁定技術(shù)谬晕,當(dāng)Model變化時(shí),View-Model會(huì)自動(dòng)更新携取,View也會(huì)自動(dòng)變化固蚤。很好做到數(shù)據(jù)的一致性
- Google官方支持databing,易于集成
缺點(diǎn):
- 數(shù)據(jù)綁定使得 Bug 很難被調(diào)試
- 數(shù)據(jù)雙向綁定不利于代碼重用及擴(kuò)展
- 代碼的閱讀性降低
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。
TODO-MVP-RXJAVA
使用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)的意義
- 避免重復(fù)造輪子戚哎,提高開發(fā)效率
- 減低耦合度裸诽,提高復(fù)用性
- 保持團(tuán)隊(duì)的技術(shù)方案統(tǒng)一性
- 便于維護(hù)升級(jí)
基礎(chǔ)組件化
通常項(xiàng)目中常用的結(jié)構(gòu)如下:
看似沒什么問題,但通常我們的一些庫都是以代碼的形式集成在代碼中型凳,隨著項(xiàng)目推進(jìn)丈冬,慢慢發(fā)現(xiàn)一些比較嚴(yán)重的問題。
- 業(yè)務(wù)代碼侵入組件代碼中 (例如一些全局的網(wǎng)絡(luò)返回響應(yīng)甘畅,直接在庫中編碼等)
- 團(tuán)隊(duì)內(nèi)部沒約束埂蕊,各自集成不同的基礎(chǔ)庫(例如圖片加載有的用Glide,有的用ImageLoader)
- 部分第三方組件停止更新疏唾,項(xiàng)目代碼耦合高蓄氧,替換新方案難
所以在實(shí)際設(shè)施組件化的過程中,建議參考:
- 獨(dú)立library庫(Common基礎(chǔ)組件)槐脏,避免在主工程中直接以代碼集成喉童,使用aar方式引用
- 第三方的庫調(diào)用最好再裝一層接口,以便后續(xù)維護(hù)升級(jí)
- 有成員專門負(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í)候... ...
業(yè)務(wù)模塊化的作用性就很明顯了
- 業(yè)務(wù)模塊間避免耦合,提高復(fù)用性
- 業(yè)務(wù)模塊獨(dú)立編譯運(yùn)行
推薦教程:
DDComponentForAndroid
Android徹底組件化方案實(shí)踐
總結(jié)
思考
- 項(xiàng)目架構(gòu)都是不斷演進(jìn)局扶,不是一蹴而就
- 沒有最好的架構(gòu)恨统,只有在適當(dāng)?shù)臅r(shí)機(jī),最合適的架構(gòu)
- 項(xiàng)目重構(gòu)過程是艱難的三妈,但長痛不如短痛
推薦業(yè)內(nèi)架構(gòu)演變
安居客Android項(xiàng)目架構(gòu)演進(jìn)
參考資料
Android App的設(shè)計(jì)架構(gòu):MVC,MVP,MVVM與架構(gòu)經(jīng)驗(yàn)談