天天看點

Android MVC、MVP、MVVM架構總結MVCMVPMVVM如何建構MVVM應用架構

MVC

Model

  • 實體模型(資料的擷取、存儲、資料狀态變化)

View

  • 指的是XML布局檔案或者是用Java自定義的View

Controller

-對應于Activity或者是Fragment,處理資料、業務和UI

總結:從上面這個結構來看,Android本身的設計還是符合MVC架構的,但是Android中純粹作為View的XML視圖功能太弱,我們大量處理View的邏輯隻能寫在Activity中,這樣Activity就充當了View和Controller兩個角色,直接導緻Activity中的代碼大爆炸,各層次之間的耦合情況也比較嚴重,不友善單元測試

MVP

Model

  • 實體模型(資料的擷取、存儲、資料狀态變化)

View

  • 對應于Activity和XML,負責View的繪制以及與使用者的互動

**Presenter

  • 負責完成View與Model間的互動和業務邏輯

MVP優點:

前面我們說,MVC中的Activity充當了View和Controller兩個角色,MVP就能很好地解決這個問題,其核心理念是通過一個抽象的View接口(不是真正的View層)将Presenter與真正的View層進行解耦。Persenter持有該View接口,對該接口進行操作,而不是直接操作View層。這樣就可以把視圖操作和業務邏輯解耦,進而讓Activity成為真正的View層。

MVP弊端:

  • Presenter(以下簡稱P)層與View(以下簡稱V)層是通過接口進行互動的,接口粒度不好控制。粒度太小,就會存在大量接口的情況,使代碼太過碎版化;粒度太大,解耦效果不好。同時對于UI的輸入和資料的變化,需要手動調用V層或者P層相關的接口,相對來說缺乏自動性、監聽性。如果資料的變化能自動響應到UI、UI的輸入能自動更新到資料,那該多好!
  • MVP是以UI為驅動的模型,更新UI都需要保證能擷取到控件的引用,同時更新UI的時候要考慮目前是否是UI線程,也要考慮Activity的生命周期(是否已經銷毀等)。
  • MVP是以UI和事件為驅動的傳統模型,資料都是被動地通過UI控件做展示,但是由于資料的時變性,我們更希望資料能轉被動為主動,希望資料能更有活性,由資料來驅動UI。
  • V層與P層還是有一定的耦合度。一旦V層某個UI元素更改,那麼對應的接口就必須得改,資料如何映射到UI上、事件監聽接口這些都需要轉變,牽一發而動全身。如果這一層也能解耦就更好了。

複雜的業務同時也可能會導緻P層太大,代碼臃腫的問題依然不能解決

MVVM

View

  • 對應于Activity和XML,負責View的繪制以及與使用者互動。

Model

  • 實體模型。

ViewModel

  • 負責完成View與Model間的互動,負責業務邏輯。

MVVM的目标和思想與MVP類似,利用資料綁定(

Data Binding

)、

依賴屬性(Dependency Property)

指令(Command)

路由事件(Routed Event)

等新特性,打造了一個更加靈活高效的架構。

資料驅動

在正常的開發模式中,資料變化需要更新UI的時候,需要先擷取UI控件的引用,然後再更新UI。擷取使用者的輸入和操作也需要通過UI控件的引用。在MVVM中,這些都是通過資料驅動來自動完成的,資料變化後會自動更新UI,UI的改變也能自動回報到資料層,資料成為主導因素。這樣MVVM層在業務邏輯進行中隻要關心資料,不需要直接和UI打交道,在業務處理過程中簡單友善很多。

低耦合度

MVVM模式中,資料是獨立于UI的。

資料和業務邏輯處于一個獨立的ViewModel中,ViewModel隻需要關注資料和業務邏輯,不需要和UI或者控件打交道。UI想怎麼處理資料都由UI自己決定,ViewModel不涉及任何和UI相關的事,也不持有UI控件的引用。即便是控件改變了(比如:TextView換成EditText),ViewModel也幾乎不需要更改任何代碼。它非常完美的解耦了View層和ViewModel,解決了上面我們所說的MVP的痛點

更新UI

在MVVM中,資料發生變化後,我們在工作線程直接修改(在資料是線程安全的情況下)ViewModel的資料即可,不用再考慮要切到主線程更新UI了,這些事情相關架構都幫我們做了。

團隊協作

MVVM的分工是非常明顯的,由于View和ViewModel之間是松散耦合的:一個是處理業務和資料、一個是專門的UI處理。是以,完全由兩個人分工來做,一個做UI(XML和Activity)一個寫ViewModel,效率更高。

可複用性

一個ViewModel可以複用到多個View中。同樣的一份資料,可以提供給不同的UI去做展示。對于版本疊代中頻繁的UI改動,更新或新增一套View即可。如果想在UI上做A/B Testing,那MVVM是你不二選擇。

單元測試

我們前面說過了,ViewModel層做的事是資料處理和業務邏輯,View層中關注的是UI,兩者完全沒有依賴。不管是UI的單元測試還是業務邏輯的單元測試,都是低耦合的。在MVVM中資料是直接綁定到UI控件上的(部分資料是可以直接反映出UI上的内容),那麼我們就可以直接通過修改綁定的資料源來間接做一些Android UI上的測試。

如何建構MVVM應用架構

如何分工

建構MVVM架構首先要具體了解各個子產品的分工。接下來我們來講解View、ViewModel、Model它們各自的職責所在。

View

View層做的就是和UI相關的工作,我們隻在XML、Activity和Fragment寫View層的代碼,View層不做和業務相關的事,也就是我們在Activity不寫業務邏輯和業務資料相關的代碼,更新UI通過資料綁定實作,盡量在ViewModel裡面做(更新綁定的資料源即可),Activity要做的事就是初始化一些控件(如控件的顔色,添加RecyclerView的分割線),View層可以提供更新UI的接口(但是我們更傾向所有的UI元素都是通過資料來驅動更改UI),View層可以處理事件(但是我們更希望UI事件通過Command來綁定)。簡單地說:View層不做任何業務邏輯、不涉及操作資料、不處理資料,UI和資料嚴格的分開。

ViewModel

ViewModel層做的事情剛好和View層相反,ViewModel隻做和業務邏輯和業務資料相關的事,不做任何和UI相關的事情,ViewModel 層不會持有任何控件的引用,更不會在ViewModel中通過UI控件的引用去做更新UI的事情。ViewModel就是專注于業務的邏輯處理,做的事情也都隻是對資料的操作(這些資料綁定在相應的控件上會自動去更改UI)。同時DataBinding架構已經支援雙向綁定,讓我們可以通過雙向綁定擷取View層回報給ViewModel層的資料,并對這些資料上進行操作。關于對UI控件事件的處理,我們也希望能把這些事件處理綁定到控件上,并把這些事件的處理統一化,為此我們通過BindingAdapter對一些常用的事件做了封裝,把一個個事件封裝成一個個Command,對于每個事件我們用一個ReplyCommand去處理就行了,ReplyCommand會把你可能需要的資料帶給你,這使得我們在ViewModel層處理事件的時候隻需要關心處理資料就行了,具體見MVVM Light Toolkit 使用指南的 Command 部分。再強調一遍:ViewModel 不做和UI相關的事。

Model

Model層最大的特點是被賦予了資料擷取的職責,與我們平常Model層隻定義實體對象的行為截然不同。執行個體中,資料的擷取、存儲、資料狀态變化都是Model層的任務。Model包括實體模型(Bean)、Retrofit的Service ,擷取網絡資料接口,本地存儲(增删改查)接口,資料變化監聽等。Model提供資料擷取接口供ViewModel調用,經資料轉換和操作并最終映射綁定到View層某個UI元素的屬性上。