美文网首页
MVP 模式接触

MVP 模式接触

作者: 虚心学习的小来子 | 来源:发表于2019-02-13 23:57 被阅读0次

    以前查看别人的时候会看不懂别人的项目结构,里面有个 presenter,其实代码勉强看得懂,但是逻辑会感觉很混乱,所以后来学习了下 MVP 模式,现在需要整理一下。

    MVC 和 MVP 的区别

    说起 MVP 模式不得不提起 MVC 模式,也是我们接触最多,也应该是最早接触的,虽然一开始的时候感觉自己写的连 MVC 模式都谈不上😁。
    MVC 模式的全程是 Model-View-Controller

    • Model 业务逻辑和实体对象
    • View 布局文件
    • Controller 控制器,也就是常说的 Activity

    MVC 模式在小型的项目上面很适用,说白了就是简单粗暴,逻辑简单,View 就是布局,实际的关于数据绑定的工作都是交给 Activity 来完成,这样子搞得 Activity 又像 Controller 又像是 View,借用网上的图来表示这种关系


    image.png

    也就是说由于 Activity 的职责很模糊,就会导致 Data 和 View 的关系很乱。

    而如果换做是 MVP 模式的话,关系则就会清晰很多


    image.png

    其中 MVP 代表的是 Model-View-Presenter,其中最大的特点就是 Presenter,它是 Model 和 View 之间的桥梁,它们分别的作用如下所示:

    • View 对应着Activity,对应着 View 的绘制和用户之间的 ui 交互
    • Model 和在 MVC 里面的作用一样是业务逻辑和实体对象
    • Presenter 负责完成 View 和 Model 之间的交互。

    和上面的图描述的一样,接下来的一张图则更加明了,是一张很经典的描述两种模式区别的图


    image.png

    总结

    MVP 减少了 Activity 要做的事情,简化了它的代码,把许多事情放到 Presenter 里面去完成,模块划分清楚,层次清楚,从而降低了耦合(这里的低耦合,我通俗的理解就是在 MVP 模式里面,View 和 Presenter 之间,Presenter 和 Model之间可能互相都持有引用(这里错了,是只能 Presenter 持有 Model),但是 View 不会持有 Presenter 的引用,反之也没有)。

    例子分析

    这里我们拿一个登录的例子来说这个问题,首先我们先看下这个项目架构,是不是感觉分的很清晰,Model 层,Presenter 层和 View 层都分的很清楚。

    image.png

    Model 层实现

    userBean 类

    public class UserBean {
    
        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(" + "\n" + "userName = " + userName + "\n" + "password = " + password + ")";
        }
    
    }
    
    

    定义的 LoginModel 接口规定 Model 类要实现的功能,当然是登录,但是这里要注意的是这里面使用的 OnLoginFinishListener 这个接口是 Presenter 里面的,通过它,Presenter 才能知道是否登录成功。

    public interface LoginModel {
    
        void login(UserBean userBean, OnLoginFinishListener onLoginFinishListener);
    
    }
    

    接着是 LoginModelImpl 这个 LoginModel 的实现类

    public class LoginModelImpl implements LoginModel {
    
        @Override
        public void login(UserBean userBean, final OnLoginFinishListener onLoginFinishListener) {
    
            final String userName = userBean.getUserName();
            final String password = userBean.getPassword();
    
            new Handler().postDelayed(new Runnable() {
                @Override
                public void run() {
    
                    boolean error = false;
    
                    if (userName == null || userName.isEmpty()) {
                        onLoginFinishListener.onUserError();
                        error = true;
                    }
    
                    if (password == null || password.isEmpty()) {
                        onLoginFinishListener.onPasswordError();
                        error = true;
                    }
    
                    if (!error) {
                        onLoginFinishListener.onSuccess();
                    }
    
                }
            }, 2000);
    
        }
    
    }
    
    

    View 类的实现

    LoginView 接口,定义 Acitivity 要完成哪些交互。

    public interface LoginView {
    
        void setUserError();
    
        void setPasswordError();
    
        void onSuccess();
    
    }
    

    接着是这个接口的实现类,在这里面实例化一个 Presenter 并持有它,通过 presenter 的实例对象来完成具体的登录和 onDestroy 里面的释放操作,释放掉对 view 的持有,也就是 activity 的持有(这里涉及内存泄漏的知识)。同时也要实现一些 ui 的交互,也就是 LoginView 接口里面定义的方法。

    public class LoginActivity extends AppCompatActivity implements View.OnClickListener, LoginView {
    
        private EditText userEditText;
        private EditText passwordEditText;
        private Button loginButton;
        private LoginPresenter loginPresenter;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_login);
            userEditText = (EditText)findViewById(R.id.et_user_name);
            passwordEditText = (EditText)findViewById(R.id.et_password);
            loginButton = (Button)findViewById(R.id.btn_login);
            loginButton.setOnClickListener(this);
            loginPresenter = new LoginPresenterImpl(this);
    
        }
    
        @Override
        protected void onDestroy() {
            loginPresenter.onDestroy();
            super.onDestroy();
        }
    
        @Override
        public void onClick(View v) {
            switch (v.getId()) {
                case R.id.btn_login:
                    UserBean userBean = new UserBean();
                    userBean.setUserName(userEditText.getText().toString());
                    userBean.setPassword(passwordEditText.getText().toString());
                    loginPresenter.validateUser(userBean);
                    break;
            }
        }
    
        @Override
        public void setUserError() {
            Toast.makeText(this, "用户名错误", Toast.LENGTH_SHORT).show();
        }
    
        @Override
        public void setPasswordError() {
            Toast.makeText(this, "密码错误", Toast.LENGTH_SHORT).show();
        }
    
        @Override
        public void onSuccess() {
            Toast.makeText(this, "登录成功", Toast.LENGTH_SHORT).show();
        }
    
    }
    
    

    最重要的 Presenter 层

    LoginPresenter 类,只用实现两个方法,一个是登录,一个是销毁。

    public interface LoginPresenter {
    
        void validateUser(UserBean userBean);
    
        void onDestroy();
    
    }
    
    

    之前提到的 OnLoginFinishListener

    public interface OnLoginFinishListener {
    
        void onUserError();
    
        void onPasswordError();
    
        void onSuccess();
    
    }
    

    LoginPresenter 的实现类,这里在登录方法里面调用 Model 的登录,并且在登录的回调里面调用 LoginView 的方法,通过这么做来链接 Model 层和 View 层,由此可见对于 MVP 模式而言,最重要的是 Presenter 层,View 层和 Model 层只要管好自己的事,Model 层管好业务逻辑,View 层管好 ui 交互,而对于 presenter 来说最重要的就是处理两者之间的关系,作为一个协调者。

    相关文章

      网友评论

          本文标题:MVP 模式接触

          本文链接:https://www.haomeiwen.com/subject/pxtseqtx.html