Android 架構系列:
Android 架構一:Android 架構淺析
Android 架構二:縱向橫向結合構建項目
Android 架構三:組件化思想
Android 架構四:組件化架構實戰
Android 架構五:MVVM+Data Binding構建項目
……
一、前言
我們都知道,Web的架構經過多年的發展已經非常成熟了,我們常用的SSM,SSH等等,架構都非常標準。個人認為,Web服務邏輯比較清晰,目的明確,流程也相對固定,從服務器收到請求開始,經過一系列的的攔截器,過濾器->被轉發到控制器手中->控制器再調用服務->服務再調用DAO獲取想要的數據->最后把數據返回給web層。哪怕中間增加一些東西,如緩存什么的。他的模型依然是以用戶請求的線程為生命周期,經過一個個切面(層)的結構,感覺類似于流水線的結構吧。
而Android App則有所不同,他沒有像用戶請求這樣一個統一的出發點,最接近的可能是來自于UI的事件,然而遠不僅僅于此。根據app不同的需求,其結構也會千差萬別,所以很難有較為統一的架構。
但是客戶端類app確實是較為常見的App類型,其結構還是有跡可循的。
我們知道,Android 常見架構有MVC、MVP和MVVM,還有最近非常流行的組件化就是指將應用根據業務需求劃分成各個模塊來進行開發,每個模塊又可以編譯成獨立的APP進行開發。理論上講,組件化和前面三種架構設計不是一個層次的。它們之間的關系是,組件化的各個組件可以使用前面三種架構設計。
我們只有了解了這些架構設計的特點之后,才能在進行開發的時候選擇適合自己項目的架構模式。
下面,我們就來了解一下,這幾個架構吧。
二、MVC
1、MVC定義
MVC (Model-View-Controller, 模型-視圖-控制器),標準的MVC是這個樣子的:
- 模型層 (Model):業務邏輯對應的數據模型,無View無關,而與業務相關;
- 視圖層 (View):一般使用XML或者Java對界面進行描述;
- 控制層 (Controllor):在Android中通常指Activity和Fragment,或者由其控制的業務類。
2、MVC架構優缺點
Activity并非標準的Controller,它一方面用來控制了布局,另一方面還要在Activity中寫業務代碼,造成了Activity既像View又像Controller。
在Android開發中,就是指直接使用Activity并在其中寫業務邏輯的開發方式。顯然,一方面Activity本身就是一個視圖,另一方面又要負責處理業務邏輯,因此邏輯會比較混亂。
這類App一般會定義一個BaseActivity,BaseActivity內部實現了網絡的異步請求,本地數據的存儲加,數據庫訪問載等復用性較強的邏輯。邏輯控制則在對應的Activity中實現。
Activity過于臃腫,往往一個Activity成千上萬行代碼。View層的XML控制力其實非常弱,眾多的View處理還是要放在Activity進行,這樣的話,Activity就既包含了View又包含了Controller,耦合高,不利于測試擴展,可讀性也變差。
所以,這種開發方式不太適合Android開發。
三、 MVP
1、MVP定義
MVP (Model-View-Presenter) 是MVC的演化版本,幾個主要部分如下:
- 模型層 (Model):主要提供數據存取功能。
- 視圖層 (View):處理用戶事件和視圖。在Android中,可能是指Activity、Fragment或者View。
- 展示層 (Presenter):負責通過Model存取書數據,連接View和Model,從Model中取出數據交給View。
所以,對于MVP的架構設計,我們有以下幾點需要說明:
- 這里的Model是用來存取數據的,也就是用來從指定的數據源中獲取數據,不要將其理解成MVC中的Model。在MVC中Model是數據模型,在MVP中,我們用Bean來表示數據模型。
- Model和View不會直接發生關系,它們需要通過Presenter來進行交互。在實際的開發中,我們可以用接口來定義一些規范,然后讓我們的View和Model實現它們,并借助Presenter進行交互即可。
實際上,MVP的原理就是View通過Presenter獲取數據,獲取到數據之后再回調View的方法來展示數據。
2、MVC 和 MVP 的區別
- MVC 中是允許 Model 和 View 進行交互的,而MVP中,Model 與 View 之間的交互由Presenter完成;
- MVP 模式就是將 P 定義成一個接口,然后在每個觸發的事件中調用接口的方法來處理,也就是將邏輯放進了 P 中,需要執行某些操作的時候調用 P 的方法就行了。
4、MVP的優缺點
優點:
- 降低耦合度,實現了 Model 和 View 真正的完全分離,可以修改 View 而不影響 Modle;
- 模塊職責劃分明顯,層次清晰;
- 隱藏數據;
- Presenter 可以復用,一個 Presenter 可以用于多個 View,而不需要更改 Presenter 的邏輯;
- 利于測試驅動開發,以前的Android開發是難以進行單元測試的;
- View 可以進行組件化,在MVP當中,View 不依賴 Model。
缺點:
- Presenter 中除了應用邏輯以外,還有大量的 View->Model,Model->View 的手動同步邏輯,造成 Presenter 比較笨重,維護起來會比較困難;
- 由于對視圖的渲染放在了 Presenter 中,所以視圖和 Presenter 的交互會過于頻繁;
- 如果 Presenter 過多地渲染了視圖,往往會使得它與特定的視圖的聯系過于緊密,一旦視圖需要變更,那么Presenter也需要變更了。
綜上,雖然MVP是在MVC的基礎上演變而來,并且大大緩解了在Android上的Controller過于龐大的問題,但是,它并不是Android APP的最理想的架構,于是,就引出了下面的 MVVM 機構。
四、MVVM
1、定義
MVVM 是 Model-View-ViewModel 的簡寫。它本質上就是 MVP 的改進版。MVVM 就是將其中的 View 的狀態和行為抽象化,讓我們將視圖 UI 和業務邏輯分開。
- 模型層 (Model):負責從各種數據源中獲取數據;
- 視圖層 (View):在 Android 中對應于 Activity 和 Fragment,用于展示給用戶和處理用戶交互,會驅動 ViewModel 從 Model 中獲取數據;
- ViewModel 層:用于將 Model 和 View 進行關聯,我們可以在 View 中通過 ViewModel 從 Model 中獲取數據;當獲取到了數據之后,會通過自動綁定,比如 DataBinding,來將結果自動刷新到界面上。
使用 Google 官方的 Android Architecture Components ,我們可以很容易地將 MVVM 應用到我們的應用中。
2、MVVM與MVP區別
我們再來看看MVP的原理
由兩者的原理圖,可以看到 ViewModel 承擔了 Presenter 中與 view和 Model 交互的職責,與 MVP模式不同的是,VM與 V 之間是通過 Datebingding 實現的,而 P是持有 View 的對象,直接調用 View 中的一些接口方法來實現。
ViewModel可以理解成是View的數據模型和Presenter的合體。它通過雙向綁定(松耦合)解決了MVP中Presenter與View聯系比較緊密的問題。
3、MVVM 的優點和缺點
MVVM模式和MVC模式一樣,主要目的是分離視圖(View)和模型(Model),它有以下優缺點。
優點:
- 低耦合:視圖(View)可以獨立于Model變化和修改,一個 ViewModel 可以綁定到不同的 View 上,當 View 變化的時候 Model 可以不變,當 Model 變化的時候 View 也可以不變。
- 可重用性:你可以把一些視圖邏輯放在一個 ViewModel 里面,讓很多 view 重用這段視圖邏輯。
- 獨立開發:開發人員可以專注于業務邏輯和數據的開發(ViewModel),設計人員可以專注于頁面設計。
- 可測試:界面素來是比較難于測試的,而現在測試可以針對 ViewModel 來寫。
缺點:
- 1、數據綁定使得 Bug 很難被調試。你看到界面異常了,有可能是你 View 的代碼有 Bug,也可能是 Model 的代碼有問題。數據綁定使得一個位置的 Bug 被快速傳遞到別的位置,要定位原始出問題的地方就變得不那么容易了。不過,貌似google最新推出的data binding已經解決該問題,待嘗試。
- 2、一個大的模塊中,model也會很大,雖然使用方便了也很容易保證了數據的一致性,當長期持有,不釋放內存,就造成了花費更多的內存。這個問題都不大,其實沒有必要把一個超級大模塊的數據都整合到一個面面俱到的model, 我們可以把巨型模塊拆分成若干小模塊,這也符合高內聚低耦合的設計思想。
- 3、數據雙向綁定不利于代碼重用。客戶端開發最常用的重用是View,但是數據雙向綁定技術,讓你在一個View都綁定了一個model,不同模塊的model都不同。那就不能簡單重用View了。
五、MVC、MVP與MVVM的關系
MVVM可以算是MVP的升級版,其中的VM是ViewModel的縮寫,ViewModel可以理解成是View的數據模型和Presenter的合體,ViewModel和View之間的交互通過Data Binding完成,而Data Binding可以實現雙向的交互,這就使得視圖和控制層之間的耦合程度進一步降低,關注點分離更為徹底,同時減輕了Activity的壓力。
我們對比一下三者的原理圖,看看他們的異同
剛開始理解這些概念的時候認為這幾種模式雖然都是要將view和model解耦,但是非此即彼,沒有關系,一個應用只會用一種模式。后來慢慢發現世界絕對不是只有黑白兩面,中間最大的一塊其實是灰色地帶,同樣,這幾種模式的邊界并非那么明顯,可能你在自己的應用中都會用到。實際上也根本沒必要去糾結自己到底用的是MVC、MVP還是MVVP,不管黑貓白貓,捉住老鼠就是好貓。
1、MVC->MVP->MVVM演進過程
MVC -> MVP -> MVVM 這幾個軟件設計模式是一步步演化發展的,MVVM 是從 MVP 的進一步發展與規范,MVP 隔離了MVC中的 M 與 V 的直接聯系后,靠 Presenter 來中轉,所以使用 MVP 時 P 是直接調用 View 的接口來實現對視圖的操作的,這個 View 接口的東西一般來說是 showData、showLoading等等。M 與 V已經隔離了,方便測試了,但代碼還不夠優雅簡潔,所以 MVVM 就彌補了這些缺陷。在 MVVM 中就出現的 Data Binding 這個概念,意思就是 View 接口的 showData 這些實現方法可以不寫了,通過 Binding 來實現。
同
如果把這三者放在一起比較,先說一下三者的共同點,也就是Model和View:
Model:數據對象,同時,提供本應用外部對應用程序數據的操作的接口,也可能在數據變化時發出變更通知。Model不依賴于View的實現,只要外部程序調用Model的接口就能夠實現對數據的增刪改查。
View:UI層,提供對最終用戶的交互操作功能,包括UI展現代碼及一些相關的界面邏輯代碼。
異
三者的差異在于如何粘合View和Model,實現用戶的交互操作以及變更通知
- Controller
Controller接收View的操作事件,根據事件不同,或者調用Model的接口進行數據操作,或者進行View的跳轉,從而也意味著一個Controller可以對應多個View。Controller對View的實現不太關心,只會被動地接收,Model的數據變更不通過Controller直接通知View,通常View采用觀察者模式監聽Model的變化。
- Presenter
Presenter與Controller一樣,接收View的命令,對Model進行操作;與Controller不同的是Presenter會反作用于View,Model的變更通知首先被Presenter獲得,然后Presenter再去更新View。一個Presenter只對應于一個View。根據Presenter和View對邏輯代碼分擔的程度不同,這種模式又有兩種情況:Passive View和Supervisor Controller。
- ViewModel
注意這里的“Model”指的是View的Model,跟MVVM中的一個Model不是一回事。所謂View的Model就是包含View的一些數據屬性和操作的這么一個東東,這種模式的關鍵技術就是數據綁定(data binding),View的變化會直接影響ViewModel,ViewModel的變化或者內容也會直接體現在View上。這種模式實際上是框架替應用開發者做了一些工作,開發者只需要較少的代碼就能實現比較復雜的交互。
一點心得
MVP和MVVM完全隔離了Model和View,但是在有些情況下,數據從Model到ViewModel或者Presenter的拷貝開銷很大,可能也會結合MVC的方式,Model直接通知View進行變更。在實際的應用中很有可能你已經在不知不覺中將幾種模式融合在一起,但是為了代碼的可擴展、可測試性,必須做到模塊的解耦,不相關的代碼不要放在一起。
個人理解,在廣義地談論MVC架構時,并非指本文中嚴格定義的MVC,而是指的MV*,也就是視圖和模型的分離,只要一個框架提供了視圖和模型分離的功能,我們就可以認為它是一個MVC框架。在開發深入之后,可以再體會用到的框架到底是MVC、MVP還是MVVM。
五、組件化
所謂的組件化,通俗理解就是將一個工程分成各個模塊,各個模塊之間相互解耦,可以獨立開發并編譯成一個獨立的 APP 進行調試,然后又可以將各個模塊組合起來整體構成一個完整的 APP。它的好處是當工程比較大的時候,便于各個開發者之間分工協作、同步開發;被分割出來的模塊又可以在項目之間共享,從而達到復用的目的。組件化有諸多好處,尤其適用于比較大型的項目。
由于篇幅以及組件化區別以上其它三種架構,它是一中橫向分塊的思想,我將單獨一節來講講組件化。
六、總結
MVC、MVP和MVVM各有各自的特點,可以根據應用開發的需要選擇適合自己的架構模式。組件化的目的就在于保持各個模塊之間的獨立從而便于分工協作。它們之間的關系就是,你可以在組件化的各個組件中應用前面三種架構模式的一種或者幾種。
`