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

前言

Android的開(kāi)發(fā)生態(tài)系統(tǒng)發(fā)展迅速,在開(kāi)發(fā)Android的幾年的時(shí)間里,用來(lái)構(gòu)建Android應(yīng)用的架構(gòu)與技術(shù)一直在不斷進(jìn)化。隨著項(xiàng)目的不斷更新迭代,應(yīng)用的架構(gòu)也有不一樣的變化。由于開(kāi)發(fā)人員的數(shù)量、項(xiàng)目的業(yè)務(wù)復(fù)雜度、需求的開(kāi)發(fā)時(shí)間、應(yīng)用的使用量級(jí),使用的技術(shù)架構(gòu)也不相同。沒(méi)有最好的架構(gòu),只有最合適的。通過(guò)設(shè)計(jì)使程序模塊化,做到模塊內(nèi)部的高聚合和模塊之間的低耦合。這樣做的好處是使得程序在開(kāi)發(fā)的過(guò)程中,開(kāi)發(fā)人員只需要專(zhuān)注于一點(diǎn),提高程序開(kāi)發(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ù)訪問(wèn)層。mvc的思想其實(shí)也一樣,都是一種軟件設(shè)計(jì)典范,用一種業(yè)務(wù)邏輯、數(shù)據(jù)、界面顯示分離的方法組織代碼,在改進(jìn)和個(gè)性化定制界面及用戶交互的同時(shí),不需要重新編寫(xiě)業(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ù)庫(kù)的操作、對(duì)網(wǎng)絡(luò)等的操作都應(yīng)該在Model里面處理,當(dāng)然對(duì)業(yè)務(wù)計(jì)算等操作也是必須放在的該層的

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

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

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

mvp

mvp這是目前我們項(xiàng)目中主要采用的應(yīng)用架構(gòu)方式,MVP從更早的MVC框架演變過(guò)來(lái),與MVC有一定的相似性:Controller/Presenter負(fù)責(zé)邏輯的處理,Model提供數(shù)據(jù),View負(fù)責(zé)顯示。mvp架構(gòu)的演變,解決了Activity代碼臃腫的問(wèn)題,當(dāng)我們將Activity復(fù)雜的邏輯處理移至另外的一個(gè)類(lèi)(Presenter)中時(shí),Activity其實(shí)就是MVP模式中的View,它負(fù)責(zé)UI元素的初始化,建立UI元素與Presenter的關(guān)聯(lián)(Listener之類(lèi)),同時(shí)自己也會(huì)處理一些簡(jiǎn)單的邏輯(復(fù)雜的邏輯交由 Presenter處理)。項(xiàng)目開(kāi)發(fā)中,UI是容易變化的,且是多樣的,一樣的數(shù)據(jù)會(huì)有N種顯示方式;業(yè)務(wù)邏輯也是比較容易變化的。為了使得應(yīng)用具有較大的彈性,我們期望將UI、邏輯(UI的邏輯和業(yè)務(wù)邏輯)和數(shù)據(jù)隔離開(kāi)來(lái),而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用來(lái)降低耦合)

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

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

優(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. 更便于測(cè)試。把邏輯放在Presenter中,就可以脫離用戶接口來(lái)測(cè)試邏輯(單元測(cè)試)

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

mvvm

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

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

View和Model之間通過(guò)Android Data Binding技術(shù),實(shí)現(xiàn)視圖和數(shù)據(jù)的雙向綁定;ViewModel持有Model的引用,通過(guò)Model的方法請(qǐng)求數(shù)據(jù);獲取數(shù)據(jù)后,通過(guò)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)用的問(wèn)題,界面由數(shù)據(jù)進(jìn)行驅(qū)動(dòng),響應(yīng)界面操作無(wú)需由View(Activity)傳遞,數(shù)據(jù)的變化也無(wú)需Presenter調(diào)用View(Activity)實(shí)現(xiàn),使得數(shù)據(jù)傳遞的過(guò)程更加簡(jiǎn)潔,高效。

推薦教程:
精通 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)目目的是通過(guò)展示各種架構(gòu)app的不同方式來(lái)幫助開(kāi)發(fā)者解決架構(gòu)問(wèn)題。項(xiàng)目中通過(guò)不同的架構(gòu)概念及方式實(shí)現(xiàn)了功能相同的app。

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

TODO-MVP-RXJAVA

115圖片20180108151621.png

使用RXJAVA對(duì)數(shù)據(jù)流進(jìn)行處理,并且通過(guò)Repository進(jìn)行數(shù)據(jù)的集中管理,通過(guò)協(xié)議類(lèi)XXXContract來(lái)對(duì)View和Presenter的接口進(jìn)行內(nèi)部繼承,在presenter的實(shí)現(xiàn)類(lèi)中,可以對(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)部需要開(kāi)發(fā)多個(gè)APP,且多個(gè)APP中存在相同的業(yè)務(wù)模塊,一開(kāi)始的做法為了趕項(xiàng)目進(jìn)度可能就是黏貼復(fù)制,到后面就慢慢發(fā)現(xiàn)越來(lái)越吃力,重復(fù)勞動(dòng)。
慢慢隨著時(shí)間的推移,惡性循環(huán)。慢慢發(fā)現(xiàn)項(xiàng)目代碼結(jié)構(gòu)混亂、層次不清,各業(yè)務(wù)技術(shù)方案不統(tǒng)一;甚至連基本的包結(jié)構(gòu)也是胡亂不堪,都是不停地往上堆砌代碼添加新功能,前人挖坑后人填??梢?jiàn)組件化對(duì)于不斷迭代的項(xiàng)目有著深遠(yuǎn)的意義

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

基礎(chǔ)組件化

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

115截圖20180108161144.png

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

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

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

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

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

隨著項(xiàng)目邏輯不斷的增加,慢慢是不是發(fā)現(xiàn)代碼編譯速度是不是越來(lái)越慢?(PS:我們目前項(xiàng)目編譯一次2分鐘,且已是經(jīng)過(guò)一些優(yōu)化處理)
另外當(dāng)團(tuán)隊(duì)內(nèi)部有多個(gè)項(xiàng)目時(shí),是不是經(jīng)歷過(guò)產(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. 沒(méi)有最好的架構(gòu),只有在適當(dāng)?shù)臅r(shí)機(jī),最合適的架構(gòu)
  3. 項(xiàng)目重構(gòu)過(guò)程是艱難的,但長(zhǎng)痛不如短痛

推薦業(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 開(kāi)發(fā):由模塊化到組件化(一)

?著作權(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)容