MVP 設(shè)計(jì)模式,實(shí)戰(zhàn)理解MVP

作者: 夏至 歡迎轉(zhuǎn)載,也請(qǐng)保留這份申明,謝謝。

http://blog.csdn.net/u011418943/article/details/69840880

1、什么是MVP

MVP,全稱(chēng) Model-View-Presenter。它是從 MVC中演變過(guò)來(lái)的,它的基本思想是相通的;在MVP中,View更加專(zhuān)注于處理數(shù)據(jù)的可視化以及用戶交互,讓Model專(zhuān)注于數(shù)據(jù)的處理,而Presenter則,提供 View 與 Model 之間數(shù)據(jù)的紐帶,用于交互與數(shù)據(jù)傳輸;如下面這張圖:

這里寫(xiě)圖片描述

可以看到,在View 與 Model 之間我們是通過(guò) Presenter,也就是 interface 來(lái)實(shí)現(xiàn)view 與數(shù)據(jù)的交互的,大大降低耦合,方便進(jìn)行單元測(cè)試。至于與 MVC 的異同,自行g(shù)oogle吧,這里就不細(xì)說(shuō)了。

其實(shí),自己在寫(xiě)代碼的時(shí)候,心中有個(gè)概念就好了,view 就是UI,model就是數(shù)據(jù)處理,而persenter 則是他們的紐帶。心中有個(gè)輪廓,寫(xiě)起來(lái)就不那么費(fèi)勁了。

2、使用 MVP 的 優(yōu)缺點(diǎn)

我們?cè)谑褂靡环N設(shè)計(jì)模式的時(shí)候,首先都會(huì)問(wèn),為什么要用這種模式,能給我們帶來(lái)哪些方便?用了這種模式,它的缺點(diǎn)會(huì)不會(huì)給我的工程造成影響?
首先,優(yōu)點(diǎn)上,我們上面已經(jīng)闡述了;

  • 減低耦合,實(shí)現(xiàn)了 Model 與View 的真正分離,修改 View 而不影響 Model
  • 模塊職責(zé)分明,層次分明,便于維護(hù),多人開(kāi)發(fā)首選。
  • Presenter 可以服用,一個(gè) Presenter可以用于多個(gè) View,不用去改 Presenter
  • 利于單元測(cè)試。模塊分明,那么我們編寫(xiě)單元測(cè)試就變得很方便了,而不用特別是特別搭平臺(tái),人工模擬用戶操作等等耗時(shí)耗力的事情。

缺點(diǎn):
對(duì)于小工程,額外多出來(lái)的代碼量,和額外的代碼復(fù)雜度,畢竟那么多 interface ,但對(duì)于它的有點(diǎn)來(lái)說(shuō),完全可以接受。

3、實(shí)戰(zhàn)

我們就簡(jiǎn)單一個(gè)數(shù)據(jù)保存的例子好了。至于數(shù)據(jù)庫(kù)的保存,采用郭霖大神的 LitePal,連接如下:
http://blog.csdn.net/column/details/android-database-pro.html
先上效果:

這里寫(xiě)圖片描述

非常簡(jiǎn)單,就是獲取 EditText的數(shù)據(jù),保存在數(shù)據(jù)庫(kù),然后重新把它讀取出來(lái),結(jié)構(gòu)圖如下:


這里寫(xiě)圖片描述

首先,從上面的效果圖來(lái)看,我們需要 name 和 password 這兩個(gè)字符串,我們需要新建一個(gè) User 類(lèi),由于要用到 LitePal ,所以讓它繼承 DataSupport;如果你使用自己寫(xiě)的,那就不用繼承啥了。:

public class User extends DataSupport{
    private String username;
    private String password;
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    @Override
    public String toString() {
        return "User{" +
                "username='" + username + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
}

Model:

然后,我們思考一下,從View 傳過(guò)來(lái)的數(shù)據(jù)name和password,我們是要保存起來(lái)的,所以,我們先在 model,編寫(xiě)數(shù)據(jù)保存和讀取的方法:

public interface IUserModel {
    void saveUserData(User user);
    User readUserData(String name);
}

它的具體實(shí)現(xiàn)方法如下:

/**
 * Created by zhengshaorui on 2017/4/9.
 */
public class UserModel implements IUserModel {
    public UserModel() {
    }
    /**
     * 使用Litepal保存數(shù)據(jù)
     * @return
     */
    @Override
    public void saveUserData(User user) {
        user.save();
        lg.d("user: "+user);
    }
    /**
     * 通過(guò) name從數(shù)據(jù)庫(kù)讀取數(shù)據(jù)
     * @param name
     * @return
     */
    @Override
    public User readUserData(String name) {
        List<User> userList = DataSupport.where("username = ?",name).find(User.class);
        if (userList.size() > 0)
            return userList.get(0);
        return null;
    }
}

方法很簡(jiǎn)單,就保存一下數(shù)據(jù)和讀數(shù)據(jù)。什么?數(shù)據(jù)庫(kù)保存這樣就行了?是的,所以趕緊去學(xué)習(xí) LitePal 吧。

View:

View這里,我們是專(zhuān)注于UI的顯示和用戶交互的,上面我們通過(guò)名字的方式從數(shù)據(jù)庫(kù)中讀取,然后把它顯示出來(lái)。所以,我們需要添加 name 和password 的顯示方法,當(dāng)然還有出錯(cuò)的方法:

public interface IUserView {
    void setUserName(String userName);
    void setPassword(String password);
    void error(String errormsg);
}

然后讓mainactivity 繼承這個(gè)接口重寫(xiě)該方法:

 @Override
    public void setUserName(String userName) {
        mUserEditText.setText(userName);
    }
    @Override
    public void setPassword(String password) {
        mPassEditText.setText(password);
    }
    @Override
    public void error(String errormsg) {
        Toast.makeText(this, errormsg, Toast.LENGTH_SHORT).show();
    }

Presenter :

好了,現(xiàn)在我們的 View 和 Model 都是單獨(dú)開(kāi)了的,所以,我們需要一個(gè)紐帶,把view 和model 連接起來(lái);那就是我們的 Presenter 了:

/**
 * Created by zhengshaorui on 2017/4/9.
 */
public class UserPresenter {
    private IUserView mIUserView;
    private IUserModel mIUserModel;
    public UserPresenter(IUserView mIUserView) {
        this.mIUserView = mIUserView;
        mIUserModel = new UserModel();
    }
    /**
     * 數(shù)據(jù)保存
     * @param user
     */
    public void saveUser(User user){
        mIUserModel.saveUserData(user);
    }
    /**
     * 讀取數(shù)據(jù)
     * @param name
     */
    public void readUser(String name){
        User user =  mIUserModel.readUserData(name);
        lg.d("getread: "+user);
        if (user != null) {
            mIUserView.setUserName(user.getUsername());
            mIUserView.setPassword(user.getPassword());
        }else{
            mIUserView.error("沒(méi)有找到");
        }
    }
}

ok,其他都寫(xiě)好了,那么接下來(lái),只要寫(xiě)onclick事件就可以了:

//保存
    public void save(View view){
        User user = new User();
        user.setUsername(mUserEditText.getText().toString());
        user.setPassword(mPassEditText.getText().toString());
        mUserPresenter.saveUser(user);
    }
    //清空 edittext 
    public void clear(View view){
        mUserEditText.setText("");
        mPassEditText.setText("");
    }
    //讀數(shù)據(jù)
    public void read(View view){
        mUserPresenter.readUser(mReadEditText.getText().toString());
    }

這樣,我們就實(shí)現(xiàn)了一個(gè)簡(jiǎn)單的 MVP demo了。

疑問(wèn):

  1. 這樣,你可能會(huì)有疑問(wèn)?一個(gè)簡(jiǎn)單的demo被你寫(xiě)得這么復(fù)雜,還說(shuō)這個(gè)設(shè)計(jì)模式有多好?
  2. 這么簡(jiǎn)單的,接口都那么多,那稍微復(fù)雜點(diǎn)的,那接口不是直接上天和太陽(yáng)肩并肩了嗎?

可能很多人有這樣的疑問(wèn),是的,在一些小工程,或者一個(gè)項(xiàng)目只有一兩個(gè)人開(kāi)發(fā)的時(shí)候,你可以酌情考慮要不要使用這種模式,而使用這種模式,就考驗(yàn)?zāi)銓?duì)接口的理解和使用了。
而稍微復(fù)雜點(diǎn)的,和多人開(kāi)發(fā)的,我建議是使用這種模式的,當(dāng)然沒(méi)有完美的框架,適合自己的才是最重要的,反正我用的挺嗨的,有點(diǎn)搞逼格的感覺(jué),筆者就試過(guò)一個(gè)稍微復(fù)雜的項(xiàng)目,多人開(kāi)發(fā),最后搞得很混亂,牽一發(fā)而動(dòng)全一身;

當(dāng)然也是見(jiàn)仁見(jiàn)智,最后附上demo的下載地址:https://github.com/LillteZheng/MvpDemo

參考:http://www.itdecent.cn/p/9a6845b26856#

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,109評(píng)論 25 709
  • 作者:李旺成 時(shí)間:2016年4月3日 “Android MVP 詳解(下)”已經(jīng)發(fā)布,歡迎大家提建議。 MVP ...
    diygreen閱讀 129,343評(píng)論 85 1,321
  • 轉(zhuǎn)載至:http://www.itdecent.cn/p/9a6845b26856 “Android MVP 詳解...
    SnowDragonYY閱讀 10,417評(píng)論 5 241
  • 你永遠(yuǎn)不知道生活中下一刻你將面臨什么。 離陌還沒(méi)起床就被鈴聲吵醒了。迷糊的接了電話, “喂,你好?!?“離陌,我覺(jué)...
    靈小邪閱讀 397評(píng)論 1 0
  • 關(guān)于數(shù)組越界目前大概有兩種方式,一種是通過(guò)分類(lèi)添加安全的索引方法,第二種就是Runtime實(shí)現(xiàn),第一種如果是個(gè)人開(kāi)...
    FlyElephant閱讀 5,294評(píng)論 9 21

友情鏈接更多精彩內(nèi)容