天天看點

50個Android開發技巧(20 使用MVP模式)

一、mvp介紹

     随着ui建立技術的功能日益增強,ui層也履行着越來越多的職責。為了更好地細分視圖(view)與模型(model)的功能,讓view專注于處理資料的可視化以及與使用者的互動,同時讓model隻關系資料的處理,基于mvc概念的mvp(model-view-presenter)模式應運而生。

     在mvp模式裡通常包含4個要素:

     (1)view:負責繪制ui元素、與使用者進行互動(在android中展現為activity);

     (2)view interface:需要view實作的接口,view通過view interface與presenter進行互動,降低耦合,友善進行單元測試;

     (3)model:負責存儲、檢索、操縱資料(有時也實作一個model interface用來降低耦合);

     (4)presenter:作為view與model互動的中間紐帶,處理與使用者互動的負責邏輯。

(原文位址:)

二、為什麼使用mvp模式

     在android開發中,activity并不是一個标準的mvc模式中的controller,它的首要職責是加載應用的布局和初始化使用者界面,并接受并處理來自使用者的操作請求,進而作出響應。随着界面及其邏輯的複雜度不斷提升,activity類的職責不斷增加,以緻變得龐大臃腫。當我們将其中複雜的邏輯處理移至另外的一個類(presneter)中時,activity其實就是mvp模式中view,它負責ui元素的初始化,建立ui元素與presenter的關聯(listener之類),同時自己也會處理一些簡單的邏輯(複雜的邏輯交由presenter處理).

     另外,回想一下你在開發android應用時是如何對代碼邏輯進行單元測試的?是否每次都要将應用部署到android模拟器或真機上,然後通過模拟使用者操作進行測試?然而由于android平台的特性,每次部署都耗費了大量的時間,這直接導緻開發效率的降低。而在mvp模式中,處理複雜邏輯的presenter是通過interface與view(activity)進行互動的,這說明了什麼?說明我們可以通過自定義類實作這個interface來模拟activity的行為對presenter進行單元測試,省去了大量的部署及測試的時間。

三、mvp與mvc的異同

     mvc模式與mvp模式都作為用來分離ui層與業務層的一種開發模式被應用了很多年。在我們選擇一種開發模式時,首先需要了解一下這種模式的利弊:

     無論mvc或是mvp模式都不可避免地存在一個弊端:

          額外的代碼複雜度及學習成本。

     這就導緻了這兩種開發模式也許并不是很小型應用。

     但比起他們的優點,這點弊端基本可以忽略了:

     (1)降低耦合度

     (2)子產品職責劃分明顯

     (3)利于測試驅動開發

     (4)代碼複用

     (5)隐藏資料

     (6)代碼靈活性

     對于mvp與mvc這兩種模式,它們之間也有很大的差異。有一些程式員選擇不使用任何一種模式,有一部分原因也許就是不能區分這兩種模式差異。以下是這兩種模式之間最關鍵的差異:

     (參考文章:http://www.infragistics.com/community/blogs/todd_snyder/archive/2007/10/17/mvc-or-mvp-pattern-whats-the-difference.aspx)

     mvp模式:

view不直接與model互動,而是通過與presenter互動來與model間接互動

presenter與view的互動是通過接口來進行的,更有利于添加單元測試

通常view與presenter是一對一的,但複雜的view可能綁定多個presenter來處理邏輯     

     mvc模式:

view可以與model直接互動

controller是基于行為的,并且可以被多個view共享

可以負責決定顯示哪個view

四、利用mvp進行android開發的例子

     說了這麼多理論,現在輪到實踐了。

     現在我們來實作這樣一個android上的demo(如圖):可以從edittext讀取使用者資訊并存取,也可以根據id來從背景讀出使用者資訊并顯示。

50個Android開發技巧(20 使用MVP模式)

頁面布局很簡單,就不介紹了。下面根據mvp原則來進行編碼:

先來看看java檔案的目錄結構:

50個Android開發技巧(20 使用MVP模式)

可以發現,presenter與model、view都是通過接口來進行互動的,既降低耦合也友善進行單元測試。

(1)首先我們需要一個userbean,用來儲存使用者資訊

(2)再來看看view接口:

     根據需求可知,view可以對id、firstname、lastname這三個edittext進行讀操作,對firstname和lastname進行寫操作,由此定義iuserview接口:

(3)model接口:

     同樣,model也需要對這三個字段進行讀寫操作,并存儲在某個載體内(這不是我們所關心的,可以存在記憶體、檔案、資料庫或者遠端伺服器,但對于presenter及view無影響),定義iusermodel接口:

(4)presenter:

     至此,presenter就能通過接口與view及model進行互動了:

(5)useractivity:

     useractivity實作了iuserview及view.onclicklistener接口,同時有一個userpresenter成員變量:

重寫了onclick方法:

可以看到,view隻負責處理與使用者進行互動,并把資料相關的邏輯操作都扔給了presenter去做。而presenter調用model處理完資料之後,再通過iuserview更新view顯示的資訊。

view剩下的方法及usermodel類不是我們所關心重點,如果有興趣可以在源碼中檢視。