项目踩坑Android进阶Android进阶之路

挑战MVP

2017-06-29  本文已影响181人  程序员丶星霖

挑战MVP

MVP.jpg

前言

之前一直听说MVP,听到这种模式有多么好,但是一直没有尝试过这种模式,也没有花时间去理解它。但是听周围的朋友都在项目中使用到了这种模式,便萌生了尝试一下的念头。笨鸟,还飞得晚,活该自己落后与别人哦。来吧,下了决心,怎么也得理解一下是个什么一回事吧。总不能还停留在“最有价值球员”的认知上吧!!!

一、什么是MVP?

MVP?今年不是杜兰特吗?这个我知道啊!

逗逼.jpg

这里的MVP可不再是NBA了哦,我还是醒醒吧!天天就知道不务正业。书归正传,说到了MVP,跟我们联系比较紧密的也就是MVC了,这俩哥们儿是啥关系啊,姓氏都一样,是不是哥俩儿啊?

仔细一看,还这有那么几分神似。

MVC,全称Model—View—Controller(模型-视图-控制器),这种模式是在80年代Small talk-80出现多的一种设计模式,后来被得到了广泛的应用。

MVP,全称Model—View—Presenter(模型-视图-表示器),这种模式是由IBM开发出来的一个针对C++和Java的编程模型,大概出现于2000年,普遍认为这种模式是MVC模式的一个变种。

二、MVC与MVP的对比

代码结构 MVC MVP
Model 业务逻辑和实体模型 业务逻辑和实体模型
View 对应于布局文件 对应于Activity,负责View的绘制以及与用户交互
Controller 对应于Activity ——
Presenter —— 负责完成View与Model之间的交互

从上面的表格对比中可以看得出来,MVP大大的减少了Activity中的职责,简化其中代码量,将View与Model之间的交互的复杂逻辑代码都提取到了Presenter中进行处理。这样做的好处就是降低了耦合性,模块职责划分更明显,便于进行测试。将原本复杂的Model-View关系转变为更加清晰明了的Model-View关系。

未使用MVP.png MVP.png

下图中是MVC与MVP的图示:

MVC与MVP.png

两种模式最大的区别是:

三、MVP的优缺点对比

MVP对比 优点 缺点
1 降低耦合度,实现Model与View的完全分离 Presenter中的逻辑处理较多,是得Presenter比较臃肿,维护比较困难
2 模块职责划分明显。层次清晰 View的渲染放到了Presenter中,导致View与Presenter的交互过于频繁
3 隐藏了数据,安全性提高 View与Presenter联系紧密,一旦View发生改变,Presenter也将发生改变
4 Presenter的复用性提高 代码量增加,代码复杂度增加
5 便于进行测试
6 代码灵活性增加
7 View可以进行组件化

四、MVP剖析

M(model)层主要职责:

V(view)层主要职责:(Activity、Fragment、View、ViewGroup等)

P(presenter)层主要职责:

MVP中通常包含4个要素:

五、一次练个够

到底是个啥?还是上代码,才能更好的理解啊!是骡子是马拉出来溜溜啊~~~~

5.1先来实现一个简单的登录功能吧!(向鸿洋大神学习下!http://blog.csdn.net/lmj623565791/article/details/46596109
UI图.png
  1. 要登录总要有用户吧,来个bean!
/**
 * 用户类
 */

public class User {
    private String userName;
    private String passWord;

    public String getUserName() {
        return userName;
    }

    public void setUserName(String mUserName) {
        userName = mUserName;
    }

    public String getPassWord() {
        return passWord;
    }

    public void setPassWord(String mPassWord) {
        passWord = mPassWord;
    }
}
  1. 有了用户,他需要做什么操作呢?实现登录功能,至少有个登录吧。
public interface IUser {
    public void login(String userName,String passWord,OnLoginListener mOnLoginListener );
}
public class UserModel implements IUser {
    @Override
    public void login(final String userName, final String passWord, final OnLoginListener mOnLoginListener) {
        //模拟子线程耗时操作
        new Thread() {
            @Override
            public void run() {
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException mE) {
                    mE.printStackTrace();
                }
                //模拟登录成功
                if (userName.equals("闭关修炼") && passWord.equals("123")) {
                    User mUser = new User();
                    mUser.setUserName(userName);
                    mUser.setPassWord(passWord);
                    mOnLoginListener.loginSuccess(mUser);
                } else {
                    mOnLoginListener.loginFailed();
                }
            }
        }.start();
    }
}
public interface OnLoginListener {
    void loginSuccess(User mUser);
    void loginFailed();
}
  1. Presenter与View的交互式通过接口实现的。所以难点就是确定View中应该有什么方法,对我这个初级菜鸟来说,简直就是难于上青天啊!

登录肯定需要有用户名和密码,那么就需要在EditText中获取吧:

//登录说明了要有用户名和密码
String getUserName();
String getPassWord();

登录的过程是个耗时操作,需要给用户一个有好的提示,一般是操作ProgressBar等待框:

void showLoading();
void hideLoading();

登录存在两种情况的处理,分别是成功后和失败后的逻辑处理:

void toMainActivity(User mUser);
void showFailedError();

还有一个重置功能(当然写在一个方法中也是可以的):

void clearUserName();
void clearPassWord();

所以View的接口应该是这样的:

/**
 * View的接口
 */

public interface ILoginView {

    //登录说明了要有用户名和密码
    String getUserName();
    String getPassWord();

    //耗时操作,需要给用户一个有好的提示,一般就是操作Progress Bar
    void showLoading();
    void hideLoading();

    //登录存在两种可能要处理的情况,登陆成功于登录失败
    void toMainActivity(User mUser);
    void showFailedError();

    //重置功能
    void clearUserName();
    void clearPassWord();

}

View Interface都有了,哪个View实现就可以了啊!

public class LoginActivity extends Activity implements ILoginView {

    private TextInputEditText mEtUserName;
    private TextInputEditText mEtPassWord;
    private Button mBtnLogin;
    private Button mBtnReset;
    private ProgressBar mProgressBar;

    private UserLoginPresenter mUserLoginPresenter = new UserLoginPresenter(this);

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_login);
        initView();
    }

    //初始化
    private void initView() {
        mEtUserName = (TextInputEditText) findViewById(R.id.et_username);
        mEtPassWord = (TextInputEditText) findViewById(R.id.et_password);
        mBtnLogin = (Button) findViewById(R.id.btn_login);
        mBtnReset = (Button) findViewById(R.id.btn_reset);
        mProgressBar = (ProgressBar) findViewById(R.id.progressbar);
        mBtnLogin.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mUserLoginPresenter.login();
            }
        });
        mBtnReset.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mUserLoginPresenter.clear();
            }
        });
    }

    @Override
    public String getUserName() {
        return mEtUserName.getText().toString();
    }

    @Override
    public String getPassWord() {
        return mEtPassWord.getText().toString();
    }

    @Override
    public void showLoading() {
        mProgressBar.setVisibility(View.VISIBLE);
    }

    @Override
    public void hideLoading() {
        mProgressBar.setVisibility(View.GONE);
    }

    @Override
    public void toMainActivity(User mUser) {
        Toast.makeText(this, "登录成功!!!", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void showFailedError() {
        Toast.makeText(this, "登录失败!!!", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void clearUserName() {
        mEtUserName.setText("");
    }

    @Override
    public void clearPassWord() {
        mEtPassWord.setText("");
    }
}

哎,等等,这是啥! private UserLoginPresenter mUserLoginPresenter = new UserLoginPresenter(this);别激动,之前不就说过Presenter和View Interface进行交互嘛。现在View实现了Interface。那肯定 得有个桥梁起作用啊。

这个桥梁主要处理的就是登陆和重置的操作,要完成两者的交互,肯定需要有两者的实现类。大概就是从View中获取所需参数,交由Model进行业务处理;执行结束后的反馈和结果,在给View进行相应的显示。

/**
 * Presenter是用作Model和View之间交互的桥梁
 */

public class UserLoginPresenter {
    private IUser mIUser;
    private ILoginView mILoginView;
    private Handler mHandler = new Handler();

    public UserLoginPresenter(ILoginView mILoginView) {
        this.mILoginView = mILoginView;
        mIUser= new UserModel();
    }

    public void login(){
        mILoginView.showLoading();
        mIUser.login(mILoginView.getUserName(), mILoginView.getPassWord(), new OnLoginListener() {
            @Override
            public void loginSuccess(final User mUser) {
                //需要在UI线程执行
                mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        mILoginView.toMainActivity(mUser);
                        mILoginView.hideLoading();
                    }
                });
            }

            @Override
            public void loginFailed() {
                //需要在UI线程执行
                mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        mILoginView.showFailedError();
                        mILoginView.hideLoading();
                    }
                });
            }
        });
    }

    public void clear(){
        mILoginView.clearUserName();
        mILoginView.clearPassWord();
    }
}

参考资料:

欢迎大家关注我的微信公众号

二维码.jpg
上一篇下一篇

猜你喜欢

热点阅读