關於Android MVP模式的思考

來源:互聯網
上載者:User

標籤:

最近經常看到各種介紹MVP模式的部落格的,之前寫過不少的Android應用,在做那些應用的時候,都是要求快速完成,所以從開始設計到寫代碼就一直考慮著重用。以前寫的項目基本都是不斷重構項目,將項目代碼變得更加精簡,提高代碼之間的複用性。但是代碼並沒有特別地注重按照MVC模式或者是MVP模式來,更多的是直接考慮模組化,重用,精簡。所以看了MVP模式後,決定去總結一下自己代碼中的問題並最佳化,算是對自己之前寫的代碼的回顧。

MVP架構

MVP架構是目前在Android流行起來的架構,它非常適合用於Android開發上面。我最早接觸MVP模式是在一本敏捷開發的書上。MVP分別指代M(model),V(View),P(Presenter):
- M(Model):表示資料模型,以及相關的資料結構。
- V(View):表示視圖,主要是指UI介面相關的那些東西。在Android裡面比如說layout的xml檔案,在MVP中,很多時候Activity/Fragment也是被看做View。
- P(Presenter):可以直接理解為視圖與模型的中間紐帶。

在MVP模式中,Model和View不直接進行關聯,而是通過Presenter來進行關聯的。往往實現的方式是增加一個IModel介面和IView介面,用Model和View分別實現那兩個介面,Presenter裡面儲存IModel和IView介面類型的成員變數。

程式碼範例

下面舉一個關於Android使用者資訊的MVP模式例子。

public interface IUserView{void setName(String name);}

使用者的JavaBean—User:

class User{    private String name;    private String id;    public String getName(){        return name;    }    public String getId(){        return id;    }    public void setName(String name){        this.name = name;    }    public void setId(String id){        this.id = id;    }}

使用者模型介面

public interface IUserModel{void saveUser(User user);User load();}

真正模型

public class UserModel implements IUserModel{    void saveUser(User user){        // 儲存使用者資訊,儲存在本機資料庫中,或者xml裡面    }    User loadUser(){        // 從網路中,或者從本機快取中讀取使用者資訊        return null; //未實現    }}

Presenter:

public class UserPresenter{    private IUserView view;    private IUserModel userModel;    public UserPresenter(IUserView view){        this.view = view;        userModel = new UserModel();    }    public void loadUser(){        // 此處可能是非同步load        User user = userModel.loadUser();        view.setName(user.getName());    }}

把Activity作為View來看待

public class UserActivity extends Activity implements IUserView{    TextView tvName; //名稱對應的TextView    UserPresenter userPresenter ;    public void onCreate(Bundle bundle){        ...        userPresenter = new UserPresenter(this);        // userPresenter.loadUser(); 可以有先初始化    }    void setName(String name){        tvName.setText(name); //如果presenter的loadUser是非同步線程,這裡可以通過tvName.post來運行在UI線程。    }    void reloadUserData(){ //該函數可以某個按鈕的onClick事件裡面調用        userPresenter.loadUser(); // 可以是從網路中載入資料    }}

上面代碼中Activity不再與Model直接關聯,而是通過Presenter來間接關聯Model。並且當Model的資料變化了的時候,Presenter能夠通知View。上面的例子是View需要變化了,請求Presenter擷取資料。

分析

MVP與MVC最大的不同就是View和Model不再直接關聯。很多Android的MVC模式都是直接將Activity看作Control,這會導致整個Activity非常臃腫,因為它既然進行UI互動,還需要加上Control這部分的功能。另外即使另外建立一個Control,而把Activity只當做View的功能,如果Activity還是直接跟Model直接關聯的話,因為跟Model直接關聯,還是會在Activity增加很多操作。而使用P作為Model和View的紐帶,P可以先對模型資料進行一些處理,然後再顯示到View。另外一方面對於View的一些請求,Presenter也可以進行一些處理再去請求Model。

上面是關於代碼方面的優勢,其實通過分隔開Model和View,也是將各個模組進行瞭解耦。另外一方面通過增加IUserView和IUserModel,這樣每個部分進行單元測試也更加方便了,比如可以直接實現IUserView來類比測試Presenter。

個人覺得MVP模式適合Android應用,一個很大的原因就是Activity這種組件的存在,UI互動完全放在了Activity裡面,這導致很多時候Activity會在一不注意間就變得臃腫。View過於龐大。當然還有很多跟Android相關的優勢,比如說能夠更好地避免Activity的記憶體流失(Presenter直接引用View,而不是Activity的時候)。其實通過增加Presenter,一定程度上也增加了Presenter的複用,很多人說View和Presenter是一一對應的,但是我覺得如果不一一對應,比如說一個Activity裡麵包含多個Presenter,將Presenter細化,那樣Presenter複用的可能性也就越高了,同時也避免了Presenter過於臃腫。

一個模式最佳化過程

平時自己寫代碼的時候,其實還真的是比較少那麼明顯地使用這種MVP模式,或者說是MVC模式。更多的是模組化,類層次化(物件導向),面向切面,並且堅持代碼精簡,複用的原則。下面介紹一個將平時的項目簡化後的模式,並且通過考慮最佳化結構將模式轉變成MVP的過程。先看看下面這種類型結構:

先模組化將程式分為Fragment/Activity部分,Adapter部分,模型網路操作部分,通過將相關類進行層次化來減少類的臃腫,另外通過AOP編程的方式將一些內容從子父類中提取出來,作為一個單獨的切面。這種面向切面能夠提高代碼的複用性。

上面的類型圖裡面也有一個不合理的例子,正如上面的注釋中所說的將網路操作作為模型的一部分,而不是再添加一個介面,會導致網路操作一旦修改,會影響到Model的子類。

下面看看如何對上面的結構進行轉換。上面這種結構更多的是MVC的方式,而且是將V和C基本合在一起了,內聚在一起能夠更方面UI互動,但是也會導致臃腫。上面的圖中發現只有BaseFragment單向地去關聯Model,這樣勢必會導致Fragment增加更多的代碼來控制,因為在Android中進行網路連接是一定要在非UI線程操作的,如果Model沒有關連Fragment,必然需要將一個非同步作業放到Fragment,等待Model操作完成了後,Fragment來更新Fragment的內容。如果增加一個介面,然後Fragment實現,並且用Model引用它,那麼將能夠減少Fragment的操作,而且能夠更好地去對Model進行單元測試。如果增加一個Presenter,由Presenter與Fragment相互關聯,然後Presenter也與Model相互關聯,那麼Fragment將會大大簡化,更加專註一些其他的UI互動。增加Presenter整個架構就變成了MVP模式了。重構後的類型圖如下:

總結

模式總是堅持著複用,模組間低耦合,模組內高內聚等等原則來進行的,設計模式中就有六大原則: 單一職責原則,開閉原則,依賴倒轉原則,迪米特法則,裡氏替換原則,組合彙總原則。好的模式能夠讓人在閱讀的時候能夠很好地理解代碼,在對程式進行修改的時候能夠快速簡潔,並且不對原有代碼結構破壞。

關於Android MVP模式的思考

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.