1. 程式人生 > >android開發框架總結 (二)MVP與MVVM詳細介紹與對比,如何選擇適合的框架(乾貨!)

android開發框架總結 (二)MVP與MVVM詳細介紹與對比,如何選擇適合的框架(乾貨!)

前言

本篇文章將非常“細緻”地總結分析MVP與MVVM這兩種框架對於架構的選擇做了比較多的分析,應該是乾貨滿滿,如果你對這兩者的使用與選擇上還有迷惑之處。真的希望你能認真看完。

如果你是非常有經驗的程式猿,那就當相互學習總結,如果有不同看法還望指教。當然,我也是非常想進步的。

 


目錄

前言

1.MVP

MVP的優點

MVP的缺點

2.MVVM

MVVM的特點(優點)

MVVM的缺點

架構元件

3.MVP與MVVM的複用

4.如何選擇

5.MVP+LiveData+ModeView+LifeCycle+Dagger2


 

1.MVP

文章的一開始,先來回顧一下,什麼是MVP

MVP是在MVC的基礎上進行改造,用Present解決了V與M之間耦合度的問題,activity是作為V層的。

 

View:對應於Activity/Fragment/自定義View,主要負責UI渲染。
Model:資料獲取模組
Presenter: 負責資料處理以及View和Model的互動等,持有Model和View的引用。

在MVP模式中,View層只負責UI渲染,不再需要處理對應的業務邏輯,View層的量級大大輕化。而Presenter在獲取到Model的資料,並進行處理後,通過View層暴露的介面呼叫去更新UI,這樣View層和
Model層不互相持有引用,保證是隔離和解耦的。這樣整個業務邏輯處理和檢視的渲染是隔離的,就不會再出現上文提到的Activity/Fragment/View臃腫和混亂的問題。

我們來看一下MVP的結構圖

 

 

當然,由於MVP比較多變,不同公司不同需求結構下P層可能會有比較多架構的變化。對於虛線部分,每個人的理解不同,情況不同,選擇合適的就好,不用糾結誰對對錯,本質不變就可以的。

 


MVP的優點

1.模型與檢視完全分離

2.P層非常容易(適合)做單元測試

3.(Presener的複用)一個Presener可以用於多個檢視(View),而不需要改變Presenter的邏輯。檢視(View)的變化比模型(Model)的變化更頻繁的多 ,所以這樣超級方便。

4.(View的複用)View可以進行元件化。在MVP當中,View不依賴Model。這樣就可以讓View從特定的業務場景中脫離出來,可以說View可以做到對業務邏輯完全無知。它只需要提供一系列介面提供給上層操作。這樣就可以做高度可複用的View元件。

5.可以更高效地使用Model,因為所有的互動都發生在一個地方——Presenter內部


MVP的缺點

1.Presenter層要處理的業務邏輯過多,複雜的業務邏輯會使P層非常龐大和臃腫。

2.Presenter中除了業務邏輯以外,還有大量的View->Model,Model->View的手動同步邏輯(沒有做到像MVVM資料同步那樣一勞永逸),造成Presenter比較笨重,維護起來會比較困難

3.介面及介面中宣告的方法粒度不好把控。MVP的架構不是固定的,可能會隨著實際需求的不同而有不同的改動。P層就是一個變化比較多的地方,P層的意義是使V與M層解耦。如果粒度太小,那麼一旦業務多起來,我們的P層會非常臃腫。而如果粒度太大,那麼我們一個P層確實可以達到複用,可卻導致了我們不同需求的V層複用同一個P層介面時,要實現好多我們不需要的方法,這就是非常典型的違背了介面隔離,介面的實現類不應該實現沒有的方法。而其中有些方法是否會用到以及是否會增加或刪減還需要後續進一步確認。

4.Activity中需要宣告大量跟UI相關的方法,而相應的事件通過Presenter呼叫相關方法來實現。兩者互相引用和呼叫,存在耦合。一旦View層的UI檢視發生改變,介面中的方法就需要改變,View層和P層同時都需要修改。


關於MVP的不足我也專門寫了一篇文章從java基本原則 細數android中MVP的“七宗罪”

 

 

 

這裡插個題外話

我覺得MVP設計的初衷應該是M V P三層分別有中介軟體銜接,三者分別負責不同型別的職責,三者本應該可由不同工程人員開發,並實現無縫銜接。三者中只有P層具有獨立意志和決定權,V與M只是工具而已,V與M的替換應該是非常簡單的。

可是實際中,涉及了UI邏輯的修改時,V與P耦合度並沒有想象中那麼低,V與P相牽連,都要配合著修改,這樣P層被不是本職的工作所束縛。

Presenter雖然耦合大大降低,但是還是過於依賴Presenter

同時,MVP違背了當以職責原則,依賴倒置原則,介面隔離原則(如果粒度處理得當解決了這個問題),形式上解耦,但職責分工角度卻耦合。

總的來說就是結構很清晰易懂,寫起來不方便。

 

 

2.MVVM

 

首先了解一下,什麼是MVVM

MVVM引入了VM層替代P層(ViewModel即 Model of View)它即包含了Modle也有View的狀態。

MVVM模式中,一個ViewModel和一個View匹配,它沒有MVP中的IView介面,而是完全的和View繫結,所有View中的修改變化,都會自動更新到ViewModel中,同時ViewModel的任何變化也會自動同步到View上顯示。

這種自動同步的原因其實就是是ViewModel中的屬性都實現了observable這樣的介面,也就是說當使用屬性的set的方法,都會同時觸發屬性修改的事件,使繫結的UI自動重新整理。

在android中DataBinding幫助我們實現MVVM,在XML進行資料繫結,增加了XML的重量,不再像以前那樣僅僅是佈局,均衡了各部分的職責。

所以MVVM比MVP更升級一步,在MVP中,V是介面IView, 解決對於介面UI的耦合; 而MVVM乾脆直接使用ViewModel和UI無縫結合, ViewModel直接就能代表UI.

我們來看下MVVM的結構圖

 

 

 

MVVM的特點(優點)

1.相比於MVP,MVVM的UI做到了資料的雙向同步,因此不需要像MVP那樣手動編寫特殊用例(打比方說MVP需要寫個setInfo方法來請求資料,每次需要更新資料的時候都要呼叫這個方法。MVVM由於資料是同步的,只需要第一次將資料繫結UI就可以)所以當資料頻繁更新時,MVVM就顯得非常方便

2.ViewModel只負責提供資料給UI,處理Model的資料,不用持有V層的引用,而V層只負責監聽資料,不處理任何與資料相關的邏輯。因此,當View層UI發生變化時,VM層不需要修改,而MVP中V層要大改時,有可能要同時改P層介面與V層實現方法

3.方便協作開發,V層與P層幾乎不耦合,MVP中V層要實現P層介面的介面,而MVVM中,在V層使用組合(或者耦合度還可以更更低,使用Dagger2來解決V對VM的直接引用),由此來對其進行不同邏輯的。可以做到團隊中一人負責UI,一人負責資料處理,並行開發。其實,vm不一定不可以持有v的引用,業務不同,可能會持有!

4.觀察者模式:資料驅動,資料變->UI變,Model->View進行更新,VM只處理資料,V層只負責資料監聽與UI與UI更新

5.易於單元測試(View層不能單元測試,當然,也沒必要,因為View只負責UI繪製,不需要邏輯處理,所以V層程式碼越少越好)

資料複用,Respository模式下,VM層完全可以複用(MVP基本一個頁面一個V一個P),多個模組對同一資料來源,可以複用VM,改變V層即可

 

MVVM的缺點

1.View層採用DataBinding,xml檔案的bug不好定位(不是java語音,沒有log)

2.大模組中,model層會很大。這種情況下,雖然請求到的資料保持一致性,但是由於長時間持有不釋放,比較佔記憶體

3.資料雙向繫結,不利於程式碼複用,由於View層取到的資料是雙向繫結的,一個View只能對應一個model(View中必須宣告繫結的是那個VM層的方法,一個方法對應一個model),不同模組間model不同,View不能複用,View層不能複用。View的複用還是比較重要的

 

 

隨著Google官方推出的一系列架構元件,也大大推動了MVVM的流行。

 

架構元件

LifeCycle:可以讓控制元件監聽Activity或Fragment的生命週期,也就是V層不用處理生命週期需要處理的業務邏輯,更專心做UI繪製

WorkManager:排程任務,讓任務非同步,以及決定何時執行,執行順序(可實現鏈式任務)

LiveData:感知Fragment與Activity的生命週期(可能內部也涉及了LifeCycle,不太瞭解)的資料容器,資料一旦改變就通知UI進行介面更新。當Act元件生命週期結束時會銷燬(會佔著記憶體不放,當資料很多時不太好就是)

ViewModel:1.將檢視的資料與邏輯從有生命週期的元件中剝離,旋轉螢幕導致Act重建時資料仍會存在,直到Act完全銷燬VM菜消失(可以取代OnSaveInstance了)2.用來在act與fra中資料共享(不用使用介面或者是EventBus了)3.防止記憶體洩露(act已經退出,非同步任務還在執行)4.act中只應該處理使用者的互動和UI展示,資料處理工作可以由VM來做

 

 

現在的MVVM多是採用了DataBinding+ViewModel+LiveData的結構

這裡上使用了架構元件的MVVM程式碼  ,這種結構的好處相信大家通過上面架構元件和MVVM結構的介紹也有一定了解了。

 

 

3.MVP與MVVM的複用

MVVM中,M層與MV層可以複用,View不行

MVP中,情況就比較複雜了

目前大多數開發人員使用的MVP架構模型,基本都是“變種”,為的是減少開發成本,提高編碼速度,比如:P層和M層合到一起,也就是“網路請求(M層)”放入到P層來做。從開發長遠角度來考慮,這種方式並不理想,比如一個介面的網路請求多次使用,這個時候就要在P層多次書寫,用標準式,就解決了這個問題,可以用M層來複用解決這個問題。

 

4.如何選擇

大專案用MVP是一個不錯的主意,V層M層可以複用。P層方便做單元測試,同時P層的介面可以使在一開始對後續編碼的過程有一個整體的把控,介面使得程式碼邏輯性非常強(這點兩點很重要)。M與V並行開發,在大專案中,Model層不會像MVVM那樣佔著記憶體不釋放View也可以複用(不過個人還沒遇到View可以比較多複用的情況,希望大家補充)。同時View層的bug不像使用了DataBinding那樣的MVVM難以排查

小專案MVVM更合適,頻繁的需求更新,不會像MVP那樣P層無法複用V層只需處理UI繪製(繫結資料,甚至不用實現介面)。VM+LiveData模式下,解決了UI不活躍時候出現空指標的問題沒有P層太大的問題(介面太多)。View層與VM層是組合的關係,不像MVP那樣需要實現介面。
 

 

MVP在大的專案中的使用相對還是比較得心應手的,但是,如果你的專案不大,並且由一個人開發。你強行使用MVP,那麼你專案的前期可能得重複寫好多介面,這很讓人頭大。

 

 

5.MVP+LiveData+ModeView+LifeCycle+Dagger2

 

相比MVP,MVVM在某些方面更加友好,其實好多有經驗的工程師,更傾向於在MVP與MVVM之間取得一個折中。

這裡我們來對兩者進行優化。

一種比較優雅的寫法是MVP+LiveData+ModeView+LifeCycle+Dagger2。這裡附上了原始碼。後續會在寫一篇文章來講解這種華麗的結構,歡迎相互學習與探討,如果有不同看法,請不吝賜教,相互進步!
 

 

 

本文重在分析講解android框架的選擇,下一篇文章將會著重分析如何對其進行優化。