Android MVC、MVP模式的本質區別 及MVP升級版概述

MVC簡介

MVC模式示意圖
在這裏插入圖片描述

web中的MVC

MVC架構在web領域應用很廣泛, 用戶通過界面(view層)操作,然後相應動作會傳遞給Controller,Controller根據業務邏輯去操作數據層(Model層),然後數據層把得到的數據回調給View層進行更新,數據層可能是操作本地數據庫,也可能是訪問服務端獲取數據。 這就是MVC設計模式的基本思想。

從設計上來看,MVC較好的把View視圖層、邏輯處理層(Controller)、數據層(Model)進行了很好的分離,設計上也大致符合設計模式的基本思想:高內聚、低耦合、可複用。

Android中的MVC

但是MVC在Android中的使用卻受到了侷限性,由於Android的view佈局基本都是通過xml佈局文件來完成的,而xml佈局文件是在Activity中加載的, 即使是寫通過代碼手寫view,也通常需要Context上下文,然後像讀取SharedPreference、數據庫等,也都需要Context上下文, 所以很多時候,我們寫代碼,就直接寫在了Activity中。這就導致了Activity的任務過於繁重,當業務多了,Activity就會很臃腫。

舉個簡單的例子,我們需要在界面上顯示附近的人,那麼一進入Activity,在onCreate方法裏就去調用請求服務端得到數據,以便儘快的展示出來,這部分代碼我們可能就直接寫在Activity裏了。

有很多方案可以替代MVP,爲什麼要用MVP?

MVC, MVP模式最本質的區別

實際上,如果是一個有經驗且注重代碼解耦的程序員,他可能會把一些業務封裝到業務類或者工具類中,從而完成對Activity代碼的分層和解耦。這樣的話,其實我們不使用MVP模式也可以達到類似的效果。 但是在現實中,多數程序員還是初級程序員或者只顧完成需求的程序員, 所以這一塊他不一定能做好。 MVP模式的出現就解決了這一問題,我們之所以使用MVP,主要原因也是爲了做到代碼分層和解耦,使代碼更清晰, 而MVP模式又是一種通用的設計模式,別人把設計模式的架子都搭好了,我們只需要照貓畫虎,按照這個模式做就行了。 如果我們統一了編程規範,哪怕初級初級程序員也知道該怎麼做,即便他不知道爲什麼要這麼做。 MVP最重要的就是統一了我們的編程規範!

其實,我們如果掌握了代碼設計的幾個核心:高內聚、低耦合、可複用、易維護、易擴展、易移植等,我們就可以完全脫離設計模式的限定。之所以有MVC、MVP這樣具體的設計模式,一個是這些模式確實設計得好,所以大家都在用,也得到了大家的公認; 另一方面,就是爲了統一編程規範, 如果我們開發前就說好,這個APP,或者重構模塊使用MVP模式,那麼即便是多人開發,由於碼規範是一致的,不管是高級還是初級程序員,那麼代碼的整體分層就是差不多了。

其他設計模式也是類似的,其實都是爲了統一編程規範。比如一說單例模式、工廠模式等,你就知道代碼大體該怎麼寫。我們常說的設計模式有二十幾種,實際上遠遠不止,因爲我們在實際工作中,可能還創造了不同的設計模式,只是有的沒有形成行業統一規範,只在公司內部用等原因,讓大家所不知而已。

所以Android剛開始使用MVC設計模式,一個是使用習慣,另一個是Android誕生後還沒有一個好的統一適用於Android的設計模式,隨着不斷髮展,出現了新的公認的設計模式。

MVP模式

MVP模式示意圖
在這裏插入圖片描述

前面介紹了爲什麼誕生了MVP,現在講這個模式, MVP,分爲了三層:

  • 1、Model: 數據相關層;
  • 2、View : Activity的佈局等View相關的內容;
  • 3、Presenter:紐帶層,連接Model和View

既然前面都說了,具體的某種開發模式就是一種編程的規範,類似於單例模式都是有大體套路的,那麼MVP模式自然也就有固定的套路,MVP的開發基本流程如下:

  • 1.View層定義View.interface,用來定義View的行爲。一般由Activity或者是Fragment來實現這個接口,它定義了View視圖的各種變化,如設置Textview,加載對話框,更新進度條等。
  • 2.Model層定義Modle.interface,這個是用來定義數據層發生變化時的通知接口,因爲Model不能直接與View交互,所以它與Presenter交互,然後再通過Presenter間接達到與View的交互。
  • 3.Presenter翻譯的意思是主持人,也就是主持場合,控制節奏的意思。在這時Presenter就負責具體的業務邏輯,請求數據,把數據送到Model,或者監聽Model的數據變化,接受View層的動作,負責通過通知View層的視圖變化。

MVC和MVP的相同點

都是分爲了三層,且model層和view層的定義是相同的

MVC和MVP的不同點

MVP中Presenter取代了MVC中的Controller, 且MVC中Model、View、Controller之間相互發生通信,而MVP中Model與Presenter相互通信,View與Presenter相互通信,而Model與View之間沒有通信。

使用MVP模式的優缺點

優點: 使代碼分層更清晰,單個類的作用更單一,也更方便維護,類的作用就是要求儘量功能單一。

缺點:類會變得較多,且相同功能代碼量會上升。

所以沒有完美的方案,只有最合適的方案,根據需求選擇合適的設計模式。

代碼實踐

在這裏插入圖片描述

主要架構如上,分成了三個模塊,

1、Model 層定義了操作數據的行爲,這裏再接口IWeatherModel中進行定義,具體由WeatherModelImpl實現, 實際開發中還可由更多數據類來實現這一個統一接口;

2、 View就是視圖層, 在IWeatherView這個接口中定義View的常用操作,然後由具體的MainActivity來實現這個接口;

3、Presenter層就是紐帶層, 用來連接Model和view層,自然也就會都有Model和View層的引用,通過引用對象來進行回調, 下面看具體代碼:

model層的代碼:

public interface IWeatherModel {
    //提供數據
    public String getInfo();
    //存儲數據
    public void setInfo(String info);
}

public class WeatherModelImpl implements IWeatherModel {
    private String mInfo;
    @Override
    public String getInfo() {
        return mInfo;//具體的操作數據
    }
    @Override
    public void setInfo(String info) {
        mInfo = info;//具體的操作數據
    }
}

View層的代碼:

public interface IWeatherView {

    void onInfoUpdate(String info);//請求、更新數據的回調
    void showWaitingDialog();//家在數據的dialog
    void hideWaitingDialog();//取消dialog的顯示
}

public class MainActivity extends AppCompatActivity implements IWeatherView{
    private WeatherPresenter mPresenter;
    TextView mTextView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mPresenter = new WeatherPresenter(this);
        mTextView = findViewById(R.id.tv_info);
    }

    @Override
    public void onInfoUpdate(String info) {
        mTextView.setText(info);//更新顯示信息
    }

    @Override
    public void showWaitingDialog() {
        //顯示加載框
    }

    @Override
    public void hideWaitingDialog() {
        //隱藏加載框
    }
}

Presenter層的代碼:

public class WeatherPresenter {
    private IWeatherModel mModel; //model 請求數據,保存數據
    private IWeatherView mWeatherView;//view 顯示數據,更新數據

    public WeatherPresenter(IWeatherView weatherView) {
        mWeatherView = weatherView;
        mModel = new WeatherModelImpl();
    }

    //-------------------回調 view 方法 start ----------------------------
    private void onInfoUpdate(String info) {
        if(mWeatherView != null) {
            mWeatherView.onInfoUpdate(info);
        }
    }

    private void showWaitingDialog() {
        if(mWeatherView != null) {
            mWeatherView.showWaitingDialog();
        }
    }

    private void hideWaitingDialog() {
        if(mWeatherView != null) {
            mWeatherView.hideWaitingDialog();
        }
    }
    //-------------------回調 view 方法 end ----------------------------

    private void saveInfo(String info) {
        if(mModel != null) {
            mModel.setInfo(info);
        }
    }

    private String getInfo() {
        return mModel.getInfo();
    }

    /**
     * 提供給view層,開始請求數據
     */
    public void requestWetherInfo(){
        getNetworkInfo();;
    }

    //網絡請求得到數據後,保存到model層
    private void getNetworkInfo(){
        new Thread(new Runnable() {
            @Override
            public void run() {

                try {
                    //打開等待對話框
                    showWaitingDialog();
                    //模擬網絡耗時
                    Thread.sleep(6000);

                    String info = "21度,晴轉多雲";
                    //保存到Model層
                    saveInfo(info);
                    //從Model層獲取數據,爲了演示效果,實際開發中根據情況需要。
                    String localinfo = getInfo();
                    //通知View層改變視圖
                    onInfoUpdate(localinfo);

                } catch (InterruptedException e) {
                    e.printStackTrace();
                }finally {
                    //取消對話框
                    hideWaitingDialog();
                }
            }
        }).start();
    }

}

MVP升級版

MVP模式中,Activity可能依然臃腫

MVP中把Layout佈局和Activity作爲View層,增加了Presenter,Presenter層與Model層進行業務的交互,完成後再與View層交互(也就是Activity)進行回調來刷新UI。這樣一來,所有業務邏輯的工作都交給了Presenter中進行,使得View層與Model層的耦合度降低,Activity中的工作也進行了簡化。但是在實際項目中,隨着邏輯的複雜度越來越大,Activity臃腫的缺點仍然體現出來了,因爲Activity中還是充滿了大量與View層無關的代碼,比如各種事件的處理派發,就如MVC中的那樣View層和Controller代碼耦合在一起無法自拔。

針對MVP的優化,爲了把View再次簡化,想到兩種方式.

第一種修改

通過使用一個Presenter代理的方式,在PresenterProxy中處理各種事件機制,View中維護一個PresenterProxy對象當然Presenter中同樣實現了真實對象Presnter所實現的接口,這樣,我們同樣在View中通過代理對象調用真實對象的代碼,結構圖如下:

在這裏插入圖片描述

第二種修改

爲MVP增加一層專門用於處理各種的事件派發Controller層,Controller的作用僅僅是處理事件並根據事件通過維護的Presenter對象派發到對應的業務中,也就是說View層只有一個Controller的對象,View層不會主動去調用Presenter層,但是Controller層和Presenter都可能會回調到View層來刷新UI,所以層次結構就變成了如下:

在這裏插入圖片描述

總結

針對以上修改,可以自行實踐,這種修改可能在大型APP上就會用的到,因爲涉及到的業務會多, 爲了保持代碼的分層和解耦,肯定會增加新的層級, 也就是MVP的升級版。

還是前面講的話,只要我們設計代碼時想要遵循:高內聚、低耦合、可複用、易維護、易修改、易擴展,就得把代碼不斷拆分的更加有層級、單個類功能更加單一,也就會不斷用到新的模式,或者在現有設計模式上不斷進行優化、重組使用。

參考資料:

https://cloud.tencent.com/developer/article/1383090
https://www.cnblogs.com/tiantianbyconan/p/5036289.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章