MVP 簡介
MVP 即 Model-View-Presenter,是一種從 MVC 模型演化而來的用于 Android 開發(fā)的軟件開發(fā)模式,目標(biāo)在于將應(yīng)用程序中的用戶交互、界面顯示部分與后臺業(yè)務(wù)邏輯處理部分相分離,提升應(yīng)用程序的穩(wěn)定性和代碼的可維護(hù)、可測試性。
Model:模型層,即數(shù)據(jù)層,數(shù)據(jù)的存儲、查詢、獲取、狀態(tài)轉(zhuǎn)變等操作均交由該層完成;
View:視圖層,界面顯示、用戶交互等功能由該層實(shí)現(xiàn),在 Android 程序中,可能為一個 Activity、一個 Fragment 或一個 View 等;
Presenter:該層主要提供兩類功能:1)作為 Model 和 View 的媒介,負(fù)責(zé)在兩者間傳遞數(shù)據(jù),如從 Model 層獲取數(shù)據(jù)交給 View 進(jìn)行展示,從 View 層得到用戶輸入信息,交由 Model 加以保存等;2)處理后臺任務(wù),控制業(yè)務(wù)流程等。
上圖為 MVP 模式的基本交互結(jié)構(gòu)圖,從圖中可知:
1) MVP 結(jié)構(gòu)中 View 和 Model 并不直接進(jìn)行交互,而是通過中間媒介 Presenter 間接進(jìn)行交互;
2) 一般來說,View 和 Presenter 之間是相互持有的關(guān)系,即 View 中持有與其關(guān)聯(lián)的 Presenter,Presenter 也持有與自己進(jìn)行交互的 View,即它們通過這種一一對應(yīng)的關(guān)系進(jìn)行信息交換;而 Presenter 和 Model 間屬于單向持有關(guān)系,Presenter 中持有 Model,但 Model 中一般并不持有 Presenter,這是因?yàn)橥ǔ?Model 層與整個應(yīng)用程序相關(guān),而非與某個頁面相關(guān),如若讓 Model 層通過持有 Presenter 的引用來進(jìn)行信息交換的話,會導(dǎo)致每次對 Presenter 的增刪操作都需要修改 Model 層的代碼,不利于程序的擴(kuò)展,而通過接口回調(diào)的方式來進(jìn)行信息交換就可以避免這類情況發(fā)生,從而提升程序的可擴(kuò)展性。
MVP 模式使用注意:
- Presenter與View、Model的交互使用接口定義交互操作可以進(jìn)一步松耦合也可以通過接口更加方便地進(jìn)行單元測試;
- MVP 模式的提出主要用于隔離界面顯示與業(yè)務(wù)邏輯處理,所以在編碼時需要注意區(qū)分這兩者的界限,如對于一個 EditText,當(dāng)只需要對輸入內(nèi)容進(jìn)行簡單的判空操作時,可以直接在 View 層完成,但如若需要進(jìn)行更復(fù)雜的判斷,如判斷輸入內(nèi)容是否與已有內(nèi)容沖突時,則需要交由業(yè)務(wù)邏輯層進(jìn)行處理。
Todo 項(xiàng)目
項(xiàng)目組織結(jié)構(gòu)
項(xiàng)目地址:https://github.com/googlesamples/android-architecture
該項(xiàng)目官方明明為 Android 架構(gòu)藍(lán)圖,旨在采用不同的架構(gòu)設(shè)計模式實(shí)現(xiàn)同一個 APP 功能來輔助開發(fā)者進(jìn)行架構(gòu)選擇。該項(xiàng)目中包含了13 個已實(shí)現(xiàn)或正在實(shí)現(xiàn)中的小 Demo,本文主要基于 Todo-MVP 這個 MVP 基礎(chǔ)實(shí)例架構(gòu)進(jìn)行分析。
上圖展示了 Todo-MVP 項(xiàng)目的組織結(jié)構(gòu)。項(xiàng)目包含五部分:APP 功能實(shí)現(xiàn)部分和四個用于測試的目錄,這四個測試目錄分為兩部分,分別用于 UI 層的測試和業(yè)務(wù)邏輯層的測試。APP 功能實(shí)現(xiàn)部分根據(jù)業(yè)務(wù)功能進(jìn)行模塊劃分,主要有四個功能模塊:addedittask(增加 / 修改任務(wù))、statistics(數(shù)據(jù)統(tǒng)計)、taskdetail(任務(wù)詳情)和 tasks(任務(wù)主頁面),data 模塊即項(xiàng)目的 Model 層,用于從本地數(shù)據(jù)庫 / 遠(yuǎn)程網(wǎng)絡(luò)中獲取數(shù)據(jù)。 每一個功能模塊內(nèi)部均由四個部分構(gòu)成:XXActivity、XXFragment、XXContract 和 XXPresenter,即統(tǒng)籌控制的 Activity,用戶交互的 View,View 和 Presenter 需實(shí)現(xiàn)的接口定義和用于處理業(yè)務(wù)邏輯的 Presenter。可以看到官方示例項(xiàng)目的組織結(jié)構(gòu)簡潔明了,通過類名便可大致了解該類的主要功能,是學(xué)習(xí)的典范。
項(xiàng)目中的 MVP
下圖以 AddEditTask 作為示例,簡單描述了項(xiàng)目中的 MVP 結(jié)構(gòu)。項(xiàng)目中使用了接口來松耦合,通過 XXFragment、XXPresenter 分別作為 View 和 Presenter,data 包作為 Model 來實(shí)現(xiàn) MVP 模式。
下面腦圖對整個項(xiàng)目結(jié)構(gòu)進(jìn)行了描述。
** 要點(diǎn)分析:**
- 項(xiàng)目中 Activity 的作用在于作為一個全局控制者,創(chuàng)建當(dāng)前頁面的 Fragment 和 Presenter,并將兩者聯(lián)系起來,具體而言:Fragment 作為參數(shù)傳遞給 Presenter 的構(gòu)造函數(shù),然后 Presenter 在構(gòu)造函數(shù)中通過調(diào)用 Fragment 的 setPresenter() 方法將自身傳遞給 Fragment,這樣便建立了兩者的聯(lián)系;
- 項(xiàng)目中使用了 BaseView 和 BasePresenter 分別作為 View 和 Presenter 的基類,復(fù)用所有 View 和 Presenter 中均需使用的方法;
- 契約類:XXContract 即為項(xiàng)目中的契約類,該項(xiàng)目將 View 和 Presenter 的接口統(tǒng)一由一個契約類來進(jìn)行管理,不僅可以減少類數(shù)目,而且能夠通過該類一目了然地獲知當(dāng)前頁面中 View 和 Presenter 均有哪些主要功能,便于管理和維護(hù);
- 項(xiàng)目的模型層統(tǒng)一包含在 data 目錄中,內(nèi)部根據(jù)本地和遠(yuǎn)程進(jìn)行功能劃分,分別實(shí)現(xiàn)本地數(shù)據(jù)存儲、獲取和遠(yuǎn)程數(shù)據(jù)傳輸,清晰明了;
** 總結(jié):**
- 復(fù)雜度:本項(xiàng)目只實(shí)現(xiàn)了幾個基本功能,整體代碼量較小,復(fù)雜度較低;
-
可測試性:MVP 架構(gòu)很好地將 UI 層和業(yè)務(wù)邏輯層隔離,所以整體可測試性相當(dāng)好,可以對 UI 層和業(yè)務(wù)邏輯層分別進(jìn)行測試;
3.可維護(hù)性和可擴(kuò)展性:MVP 架構(gòu)的引入,雖然代碼量有了一定的上升,但是由于界限非常清晰,各個類職責(zé)都非常明確且單一,所以后期的擴(kuò)展,維護(hù)都會更加容易。
** 參考:**