浅析MVP模式

  MVP模式已经流行很长一段时间了,以前只是听到关于MVP的一些东西,譬如:MVP是MVC的进化版,MVP模式让View层和Model层完全解耦了。
  这里先简单回顾一下Android中MVC模式:M即是代表业务逻辑和实体模型;V即是代码对应的View,也就是界面;C即是代表控制层,对应着Activity或者Fragment;但是很多时候数据处理都在Activity或者Fragment中,View可以直接访问Model,这样就不可避免一些业务逻辑了,而且有许多业务逻辑都是在View层处理的,所以导致很多代码也就无法重用了。
  MVP模式与MVC模式最大的区别就是View不与Model打交道,而是通过Presenter来与Model交互,而且Presenter实现的逻辑代码与具体View是没有关联的,它不属于任何具体的View,而只是通过约定好的接口来交互。
  根据一个简单的例子来对MVP模式进行更深刻的理解,图1就是要实现的UI效果,一个简单的登陆界面:
这里写图片描述

图2是项目文件结构图:

这里写图片描述

图3是MVP示意图和项目中各类的对应关系,以便更好地理解:

这里写图片描述

解析:

  • UserBean是实体类,这个没什么可以讲的,直接上代码:
public class UserBean {
    private String name;
    private String password;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
}
  • Model部分是负责数据逻辑处理的部分,这个例子比较简单,就只有登陆这个功能而已,方便我们以后做业务拓展,我们先写一个UserModel 的接口UserModelInterface,代码如下:
public interface UserModelInterface {
     void login(String name,String password,LoginListener loginListener);
}

UserModel 实现代码如下:

public class UserModel implements UserModelInterface {
    @Override
    public void login(String name, String password, LoginListener loginListener) {
        //判断用户名是否为空
        if (TextUtils.isEmpty(name)){
            loginListener.nameIsEmpty();
            return;
        }
        //判断密码是否为空
        if (TextUtils.isEmpty(password)){
            loginListener.passwordIsEmpty();
            return;
        }
        //用户名和密码都不为空的情况下执行登陆操作,这里就实现登陆的网络请求代码了,直接默认登陆成功,如果登陆失败则回调loginListener.loginFailed();
        loginListener.loginSuccess();
    }
}

LoginListener 这个接口主要是用于Model和Presenter的交互,把Model的业务逻辑处理接口返回出去给Presenter,然后Presenter再通过接口(LoginView)把结果返回给View层,这大概就是MVP的模式的核心了,先不急,先上LoginListener的代码:

public interface LoginListener {
    void loginSuccess();
    void loginFailed();
    void nameIsEmpty();
    void passwordIsEmpty();
}

结合这个案例来讲,无非就两种结果,登陆成功或者失败,然后执行登陆之前要判断用户名和密码是否为空,所以就有以上四个方法了。

  • 接下来看我们用于View(MVPLoginActivity)和Presenter(LoginPresenter)交互的接口–LoginView,这个接口主要是从分析界面来得到的业务逻辑,譬如:用户有在登陆成功后我们需要进行页面的跳转,登陆失败后的我们需要弹出一个Toast来提示用户,或者更改界面提示等等。所以就有以下的代码实现:
public interface LoginView {
    String getName();
    String getPassword();
    void setName(String name);
    void setPassword(String password);
    void loginSuccess();//登录成功
    void loginFailed();//登录失败
    void nameIsEmpty();//名字为空
    void passwordIsEmpty();//密码为空
}
  • 既然说LoginView是用于View和Presenter的交互的,现在问题来了,LoginView是怎么来连接MVPLoginActivity和LoginPresenter的呢?其实很简单,只需要MVPLoginActivity去实现LoginView这个接口,直接上MVPLoginActivity代码:
public class MVPLoginActivity extends AppCompatActivity implements LoginView{

    private AutoCompleteTextView email;
    private EditText passwordEt;
    private Button email_sign_in_button;
    private LoginPresenter loginPresenter=new LoginPresenter(this);//实例化Presenter
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_login);
        email= (AutoCompleteTextView) findViewById(R.id.email);
        passwordEt= (EditText) findViewById(R.id.password);
        email_sign_in_button= (Button) findViewById(R.id.email_sign_in_button);
        email_sign_in_button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                loginPresenter.login();//登录登录登录登录登录
            }
        });
    }
    @Override
    public String getName() {
        return email.getText().toString();
    }
    @Override
    public String getPassword() {
        return passwordEt.getText().toString();
    }
    @Override
    public void setName(String name) {
        email.setText(name);
    }
    @Override
    public void setPassword(String password) {
        passwordEt.setText(password);
    }
    @Override
    public void loginSuccess() {
        Log.i("ysc","loginSuccess");
    }
    @Override
    public void loginFailed() {
        Log.i("ysc","loginFailed");
    }
    @Override
    public void nameIsEmpty() {
        Log.i("ysc","nameIsEmpty");
    }
    @Override
    public void passwordIsEmpty() {
        Log.i("ysc","passwordIsEmpty");
    }
}

在这个地方就出现了我们全面说了很多的用于View和Model交互的P(LoginPresenter)这个类了,在界面(MVPLoginActivity )实例化时也实例化LoginPresenter,在点击按钮时执行loginPresenter.login(),然后View就可以不用关系其他情况了,然后在下面看LoginPresenter的代码:

public class LoginPresenter {
    private LoginView loginView;
    private UserModel userModel;

    public LoginPresenter(LoginView loginView) {
        this.loginView = loginView;
        this.userModel=new UserModel();
    }

    public void login(){
    userModel.login(loginView.getName(), loginView.getPassword(),    new LoginListener() {
            @Override
            public void loginSuccess() {
                loginView.loginSuccess();
            }

            @Override
            public void loginFailed() {
                loginView.loginFailed();
            }

            @Override
            public void nameIsEmpty() {
                loginView.nameIsEmpty();
            }

            @Override
            public void passwordIsEmpty() {
                loginView.passwordIsEmpty();
            }
        });
    }
}

先看构造方法

public LoginPresenter(LoginView loginView) {
        this.loginView = loginView;
        this.userModel=new UserModel();
    }

先把Loginview传进来用户与view层的交互,再实例化Model(UserModel),前面有说过业务处理都在Model里,也就是userModel.login()这个方法,然后Model的处理结构通过接口LoginListener来告知LoginPreseter,LoginPresenter再通过Loginview来更新界面,这样就完成View与Model的完全解耦了。

  • LoginView:就是写一些界面需要业务逻辑,然后可以实现相对应的UI操作。
  • MVPLoginActivity:单纯的界面,实现LoginView接口,并且实例化Presenter。
  • Presenter:LoginPreseter作为MVPLoginActivity和UserModel的中间层,把通过LoginView拿到的界面数据传给UserModel处理,UserModel处理完的结果返回回来之后,通过LoginView来更新界面或者做相应的UI操作。
  • MVPLoginActivity和LoginPreseter,LoginPreseter和UserModel之间的交流都是通过接口来处理,前者通过LoginView,后者通过LoginListener。
  • 从以上分析看来MVP模式确实完成了View层和Model的完全解耦

以上就是个人看过很多篇关于MVP方面的博客资料的后,动手写的demo,顺便也写成博客,欢迎多多指正。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值