Android开发之初识MVP模式

一、什么是MVP

在介绍MVP之前,大家一定会想到MVC,我们首先简单介绍一下MVC,因为掌握了MVC对我们学习MVP是有很大帮助的。

MVC 模式代表 Model-View-Controller(模型-视图-控制器) 模式。这种模式用于应用程序的分层开发。

  1. Model(模型) - 模型代表一个存取数据的对象或 JAVA POJO。它也可以带有逻辑,在数据变化时更新控制器。比如数据库存取操作,网络操作,复杂的算法,耗时的任务等都在model层处理。
  2. View(视图) - 视图代表模型包含的数据的可视化。XML布局可以视为V层,显示Model层的数据结果。
  3. Controller(控制器) - 控制器作用于模型和视图上。它控制数据流向模型对象,并在数据变化时更新视图。它使视图与模型分离开。在Android中,Activity处理用户交互问题,因此可以认为Activity是控制器,Activity读取V视图层的数据,控制用户输入,并向Model发送数据请求。
Android开发之初识MVP模式_第1张图片
MVC

MVC模式有很多优点:
(1)耦合性低。所谓耦合性就是模块代码之间的关联程度。利用MVC框架使得View(视图)层和Model(模型)层可以很好的分离,这样就达到了解耦的目的,所以耦合性低,减少模块代码之间的相互影响。
(2)可扩展性好。由于耦合性低,添加需求,扩展代码就可以减少修改之前的代码,降低bug的出现率。
(3)模块职责划分明确。主要划分层M,V,C三个模块,利于代码的维护。

既然MVC模式这么厉害,那为什么还要发明MVP?因为使用MVC模式进行Android项目开发,随着项目的逐渐庞大,会逐渐显露出MVC模式在Android开发上的弊端:View层的XML文件能处理的事情非常有限,而作为Controller的Activity又天生具有操作UI的功能,我们在实际的项目中也会有很多UI操作在这一层,做了很多View中应该做的事情;当然Controller中也包含Controller应该做的事情,比如各种事件的派发回调,而且在这层中我们还会根据事件再去调用Model层操作数据,所以这种MVC的方式在实际项目中,Activity所在的Controller是非常臃肿的,各层次之间的耦合情况也比较严重,不方便单元测试。

讲了半天MVC,主角也该登场了。

MVP作为MVC的“进化版”,最大的改进就是它彻底剥离了视图层和业务逻辑层,让各层分工更为明确,逻辑更为清晰,代码扩展性更高,后期代码迭代更新更加容易,同时也方便了单元测试的编写。

  • View仅仅负责实现单纯的、独立的UI操作,尽量不要去维护数据(View层指Activity、Fragment这类层级)
  • Model负责处理数据请求、业务逻辑,不涉及UI操作
  • Presenter是MVP体系的控制中心,负责给View和Model安排工作 ,什么时候调用Model处理逻辑,什么时候调用View反应结果,都是Presenter说了算
  • View与Model均以接口的形式出现在Presenter中,Presenter通过调用 View与Model的实现接口,来操作 View与Model;同时Presenter也是以接口的形式出现在View中,这样Presenter与View就是通过接口相互依赖了
  • Presenter是主动方,View是被动方,对于绑定到View上的数据,不是View调用Presenter主动拉取数据,而是Presenter主动将数据推给View
Android开发之初识MVP模式_第2张图片
MVP

二、MVP的简单使用

1、定义网络请求回调接口,P层通过该接口回调通知V层

public interface IRequestView {
    /**
     * 成功
     */
    void succeed(BaseResponse baseResponse);
    /**
     * 失败
     *
     * @param message 错误提示消息
     */
    void failed(String message);
}

2、Model层负责接收来自Presenter层的数据,并开始处理数据(发起网络请求)

//登录接口
public interface IUserModel {
    /**
     * 密码登录
     *
     * @param userName 用户名
     * @param password 密码
     */
    void loginByPassword(Context context, String userName, String password, IRequestView requestView);
}
###############################################################
//实现登录请求
public class UserModel implements IUserModel {
    /**
     * 密码登录
     *
     * @param userName 用户名
     * @param password 密码
     */
    @Override
    public void loginByPassword(Context context, String userName, String password, IRequestView requestView) {
        HashMap map = new HashMap<>();
        map.put("userName", userName);
        map.put("password", password);
        RetrofitManager.getInstance(context).createReq(ApiService.class)
                .signIn(map)
                .subscribeOn(Schedulers.newThread())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new BaseObserver(context, requestView));
    }
}

3、中间层Presenter主要负责把来自View层的数据传递给Model,Model层处理完成后再经由Presenter返回给View层用于展示

public interface IUserPresenter {
    /**
     * 密码登录
     *
     * @param userName 用户名
     * @param password 密码
     */
    void loginByPassword(String userName, String password);
}
###############################################################
public class UserPresenter implements IUserPresenter {

    private Context context;
    private IUserModel userModel;
    private IRequestView requestView;

    public UserPresenter(Context context, IRequestView requestView) {
        this.context = context;
        userModel = new UserModel();
        this.requestView = requestView;
    }

    /**
     * 密码登录
     *
     * @param userName 用户名
     * @param password 密码
     */
    @Override
    public void loginByPassword(String userName, String password) {
        if (TextUtils.isEmpty(userName)) {
            ToastUtil.showShort(context.getApplicationContext(), "用户名不能为空");
            return;
        }
        if (TextUtils.isEmpty(password)) {
            ToastUtil.showShort(context.getApplicationContext(), "密码不能为空");
            return;
        }
        if (userModel != null) {
            userModel.loginByPassword(context, userName, password, requestView);
        }
    }
}

4、View层Activity部分代码

public class LoginActivity extends BaseActivity implements IRequestView {
    ……
    private UserPresenter loginPresenter;

    /**
     * 登录
     */
    private void login() {
        //手机号
        String userName = String.valueOf(loginAccountName.getText());
        //密码
        String password = String.valueOf(loginPassword.getText());
        if (loginPresenter != null) {
            loginPresenter.loginByPassword(userName, password);
        }
    }

    /**
     * 成功
     *
     * @param baseResponse
     */
    @Override
    public void succeed(BaseResponse baseResponse) {
        Object data = baseResponse.getData();
        if (data instanceof UserData) {
            //更新UI、完成其他操作
        }
    }

    /**
     * 失败
     *
     * @param message 错误提示消息
     */
    @Override
    public void failed(String message) {
        ToastUtil.showShort(getApplicationContext(), message);
    }
}

使用了MVP模式之后,我们再回过头来看看登录功能的全部代码,是不是非常简洁,各层分工也非常明确,这样以后维护起来也会事半功倍。


参考链接

https://www.jianshu.com/p/3e981d261e90
https://www.jianshu.com/p/19283a3f61de

你可能感兴趣的:(Android开发之初识MVP模式)