Android架構進階(一)——MVP

Android架構進階(一)——MVP

Android傳統MVC架構

傳統的MVC架構中,Activity與Fragment幾乎包含了M-V-C三個模塊,這種開發模式很大程度上使得所有代碼全部集中在一個類裏面,經常混亂沒有秩序,使得維護起來變得困難,經常在首次開發過程中出現問題都難以定位,跟別提後期維護,如果換人維護則更是要耗費大量時間和精力。

MVP架構

相對於MVC而言,MVP架構顯然代碼邏輯清晰很多,他將MVC中Activity與Fragment裏的關於邏輯與數據獲取的工作分配給了Model類,Presenter類,從而使Activity\Fragment實實在在的成爲了V–只處理與頁面上控件展示有關的操作。

傳統MVC架構

mvc

MVP架構

MVP

從上面的兩個圖我們可以看出,不論MVC還是MVP,M層的東西使沒有什麼變化的,我們都是在M層進行獲取數據的操作。而V層在兩種架構中就由不同的東西來擔任了:

  • MVC中的V:嚴格意義上來講就只是XML佈局文件,或者是Java的自定義控件。
    這使得C層的代碼就過分的龐大而且集中了,因爲C層不僅僅要處理業務邏輯,還要處理頁面展示等相關的邏輯(比如View的findViewById()操作、初始化),而且我們大多喜歡在業務邏輯中添加控件展示邏輯,這使得整個編碼的邏輯異常龐大,有的頁面甚至會達到一個方法幾百上千行,嚴重增加了維護的成本。
  • MVP中的V:這裏就純純的是一切處理試圖展示邏輯的代碼,通常我們把這些操作都放在Activity\Fragment中。
    這樣一來我們就可以吧業務邏輯與頁面展示邏輯分開來處理了,整體的邏輯線條也非常清晰,我們在P層中只做業務邏輯的處理,V層只做頁面展示的邏輯,用戶從V層操作進入,到P層進行業務判斷,業務邏輯中調用Model層獲取數據,Model層在回調P層返回成功失敗,業務判斷成功失敗操作再回調V層,展示給用戶。

使用MVP架構

這裏我們用常用的語言環境,也是我們日常的需求中的一部分的話來舉例子:

“這裏如果用戶點擊按鈕A 則通過調用接口B獲取數據,如果獲取數據成功,判斷數據中C是否大於D,如果是展示View-E

  • 我們將 點擊按鈕A展示View-E 看成是頁面展示邏輯,放到V層處理。
  • 我們將 調用接口B獲取數據 看成是獲取數據操作,放到M層處理
  • 我們將 獲取數據成功 然後判斷數據中 C是否大於D 這一些列操作看作是業務邏輯,我們可以放在P層

在這裏插入圖片描述

通過一個整體流程圖的展示,我們可以從中看出,用戶能感知到的一切操作都是在V層,P層沒有任何的乾貨,完全是處理V與M層之間業務的過度橋樑,M層只有數據請求,M-V-P各層分工相當明確。

MVP 架構的實例

這裏我們來把一個應用場景,用MVP的結構方式做成一個實例,已便大家理解

實例需求

最簡單的登錄流程:

  • “用戶輸入用戶名,密碼,點擊登錄,校驗輸入是否正確,不正確彈窗提示,正確則調用登錄接口,登錄失敗彈窗提示,登錄成功則將返回的數據存儲至本地”

代碼設計

這是一個最簡單的需求,也是我們日常最常見的需求之一,與MVC那種上來就寫的編碼習慣,MVP似乎多了一步設計代碼的步驟

  • 使用MVP,通常我們會封裝一個Contract的類用來管理M-V-C對應的接口模板,剩下的我們只要對應實現這三個接口即可。
public class LoginContract{
    
    public interface LoginView{
        void initView();
        void submitSuccess(Object returnData);
        void errorToast(String errMsg);
    }
    public interface LoginPresenter{
        void init();
        void submit(String username,String password);
        void loginSuccess(Object returnData);
        void loginFailed(String errMsg);
        
    }
    public interface LoginModel{
        void login(String username,String password);
    }
    
}

這裏我就不寫註釋了,大家看方法名也可以看出來方法的功能,向這樣的一個Contract類編寫完成後,基本上我們這個業務及交互的流程基本上就已經確定了

在這裏插入圖片描述

  • 這裏我們的入口是登錄頁面的Activity或者Fragment,我們將他們實現LoginContract.LoginView接口,然後重寫方法,在頁面初始化之前new一個Presenter對象,在頁面登錄按鈕點擊事件裏我們調用presenter的submit()方法把用戶名密碼傳進去。

  • 寫一個Presenter實現LoginContract.LoginPresenter,重寫裏面方法,構造方法中把登錄頁面的LoginView傳進去,並new 一個Model對象,使得presenter可以調用M層與V層的所有方法,起到橋樑的作用

  • 寫一個Model實現LoginContract.LoginModel,重寫裏面方法,並在構造方法中傳入Presenter

我們完成着些操作之後,只要按照上面流程圖中的關鍵節點,調用相應的方法,我們的登錄流程就結束了。

這裏具體代碼實現我就不寫了,太過於平平無奇,大家應該都會實現。

注意

其實上面我省略了一個步驟,就是在編寫Contract類之前,我們需要產品確認業務流程後,我們要有一個流程上的總結,也就是設計一套操作流程,你也可以畫一個流程圖,或者也可以自己構思,不做實際的產出物。

以上面的實例爲例,我的流程邏輯如下

    用戶點擊登錄 -> 校驗輸入內容

    輸入內容不合法 -> 彈框提示
    輸入內容合法   -> 調用登錄接口
  
    登錄接口成功  -> 登錄成功,獲得返回數據 -> 保存登陸數據,跳轉頁面
    登錄接口失敗  -> 彈窗提示

有了這個邏輯之後,我們才能編寫出Contract類,如果有流程圖的話,效果會更好,不過會很費時。

總結

當你一個MVP架構的頁面已經成型以後,如果需要修改業務邏輯,我們只需要針對P層的Presenter進行修改就可以,如果新增頁面展示邏輯,我們就針對V層修改對應方法,添加接口或者數據源的時候,我們在M層添加方法或更新方法就OK

  • 當你的Contract類寫好以後,你會發現,你在寫代碼之前,會花時間設計你的代碼了,你會深入的去理解業務邏輯,這樣就會減少很多的業務邏輯上的bug,如果發現bug可以在interface裏面添加,條理清晰且不易混淆。
  • MVP架構是會多處很多類,但是相比MVC,MVP更擁抱接口化編程,我們維護的時候,或者有新同事接手你的項目的時候,只要看Contract類就會理解你的業務邏輯,從而更便於維護。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章