MVP 簡(jiǎn)介
MVP 即 Model-View-Presenter秦士,是一種從 MVC 模型演化而來的用于 Android 開發(fā)的軟件開發(fā)模式瓦呼,目標(biāo)在于將應(yīng)用程序中的用戶交互划咐、界面顯示部分與后臺(tái)業(yè)務(wù)邏輯處理部分相分離,提升應(yīng)用程序的穩(wěn)定性和代碼的可維護(hù)箱熬、可測(cè)試性类垦。
Model:模型層,即數(shù)據(jù)層城须,數(shù)據(jù)的存儲(chǔ)蚤认、查詢、獲取糕伐、狀態(tài)轉(zhuǎn)變等操作均交由該層完成砰琢;
View:視圖層,界面顯示良瞧、用戶交互等功能由該層實(shí)現(xiàn)陪汽,在 Android 程序中,可能為一個(gè) Activity褥蚯、一個(gè) Fragment 或一個(gè) View 等挚冤;
Presenter:該層主要提供兩類功能:1)作為 Model 和 View 的媒介,負(fù)責(zé)在兩者間傳遞數(shù)據(jù)赞庶,如從 Model 層獲取數(shù)據(jù)交給 View 進(jìn)行展示训挡,從 View 層得到用戶輸入信息,交由 Model 加以保存等歧强;2)處理后臺(tái)任務(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温治,即它們通過這種一一對(duì)應(yīng)的關(guān)系進(jìn)行信息交換饭庞;而 Presenter 和 Model 間屬于單向持有關(guān)系,Presenter 中持有 Model熬荆,但 Model 中一般并不持有 Presenter舟山,這是因?yàn)橥ǔ?Model 層與整個(gè)應(yīng)用程序相關(guān),而非與某個(gè)頁面相關(guān)卤恳,如若讓 Model 層通過持有 Presenter 的引用來進(jìn)行信息交換的話累盗,會(huì)導(dǎo)致每次對(duì) Presenter 的增刪操作都需要修改 Model 層的代碼,不利于程序的擴(kuò)展突琳,而通過接口回調(diào)的方式來進(jìn)行信息交換就可以避免這類情況發(fā)生若债,從而提升程序的可擴(kuò)展性。
MVP 模式使用注意:
- Presenter與View拆融、Model的交互使用接口定義交互操作可以進(jìn)一步松耦合也可以通過接口更加方便地進(jìn)行單元測(cè)試蠢琳;
- MVP 模式的提出主要用于隔離界面顯示與業(yè)務(wù)邏輯處理啊终,所以在編碼時(shí)需要注意區(qū)分這兩者的界限,如對(duì)于一個(gè) EditText傲须,當(dāng)只需要對(duì)輸入內(nèi)容進(jìn)行簡(jiǎn)單的判空操作時(shí)蓝牲,可以直接在 View 層完成,但如若需要進(jìn)行更復(fù)雜的判斷泰讽,如判斷輸入內(nèi)容是否與已有內(nèi)容沖突時(shí)例衍,則需要交由業(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è)計(jì)模式實(shí)現(xiàn)同一個(gè) APP 功能來輔助開發(fā)者進(jìn)行架構(gòu)選擇佛玄。該項(xiàng)目中包含了13 個(gè)已實(shí)現(xiàn)或正在實(shí)現(xiàn)中的小 Demo,本文主要基于 Todo-MVP 這個(gè) MVP 基礎(chǔ)實(shí)例架構(gòu)進(jìn)行分析累澡。
上圖展示了 Todo-MVP 項(xiàng)目的組織結(jié)構(gòu)翎嫡。項(xiàng)目包含五部分:APP 功能實(shí)現(xiàn)部分和四個(gè)用于測(cè)試的目錄,這四個(gè)測(cè)試目錄分為兩部分永乌,分別用于 UI 層的測(cè)試和業(yè)務(wù)邏輯層的測(cè)試惑申。APP 功能實(shí)現(xiàn)部分根據(jù)業(yè)務(wù)功能進(jìn)行模塊劃分,主要有四個(gè)功能模塊:addedittask(增加 / 修改任務(wù))翅雏、statistics(數(shù)據(jù)統(tǒng)計(jì))圈驼、taskdetail(任務(wù)詳情)和 tasks(任務(wù)主頁面),data 模塊即項(xiàng)目的 Model 層望几,用于從本地?cái)?shù)據(jù)庫 / 遠(yuǎn)程網(wǎng)絡(luò)中獲取數(shù)據(jù)绩脆。 每一個(gè)功能模塊內(nèi)部均由四個(gè)部分構(gòu)成:XXActivity、XXFragment橄抹、XXContract 和 XXPresenter靴迫,即統(tǒng)籌控制的 Activity,用戶交互的 View楼誓,View 和 Presenter 需實(shí)現(xiàn)的接口定義和用于處理業(yè)務(wù)邏輯的 Presenter玉锌。可以看到官方示例項(xiàng)目的組織結(jié)構(gòu)簡(jiǎn)潔明了疟羹,通過類名便可大致了解該類的主要功能主守,是學(xué)習(xí)的典范。
項(xiàng)目中的 MVP
下圖以 AddEditTask 作為示例榄融,簡(jiǎn)單描述了項(xiàng)目中的 MVP 結(jié)構(gòu)参淫。項(xiàng)目中使用了接口來松耦合,通過 XXFragment愧杯、XXPresenter 分別作為 View 和 Presenter涎才,data 包作為 Model 來實(shí)現(xiàn) MVP 模式。
下面腦圖對(duì)整個(gè)項(xiàng)目結(jié)構(gòu)進(jìn)行了描述力九。
** 要點(diǎn)分析:**
- 項(xiàng)目中 Activity 的作用在于作為一個(gè)全局控制者耍铜,創(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)一由一個(gè)契約類來進(jìn)行管理章鲤,不僅可以減少類數(shù)目,而且能夠通過該類一目了然地獲知當(dāng)前頁面中 View 和 Presenter 均有哪些主要功能咆贬,便于管理和維護(hù)败徊;
- 項(xiàng)目的模型層統(tǒng)一包含在 data 目錄中,內(nèi)部根據(jù)本地和遠(yuǎn)程進(jìn)行功能劃分掏缎,分別實(shí)現(xiàn)本地?cái)?shù)據(jù)存儲(chǔ)皱蹦、獲取和遠(yuǎn)程數(shù)據(jù)傳輸,清晰明了眷蜈;
** 總結(jié):**
- 復(fù)雜度:本項(xiàng)目只實(shí)現(xiàn)了幾個(gè)基本功能沪哺,整體代碼量較小,復(fù)雜度較低酌儒;
-
可測(cè)試性:MVP 架構(gòu)很好地將 UI 層和業(yè)務(wù)邏輯層隔離辜妓,所以整體可測(cè)試性相當(dāng)好,可以對(duì) UI 層和業(yè)務(wù)邏輯層分別進(jìn)行測(cè)試忌怎;
3.可維護(hù)性和可擴(kuò)展性:MVP 架構(gòu)的引入籍滴,雖然代碼量有了一定的上升,但是由于界限非常清晰榴啸,各個(gè)類職責(zé)都非常明確且單一孽惰,所以后期的擴(kuò)展,維護(hù)都會(huì)更加容易鸥印。
** 參考:**