美文网首页
Android开发之初识MVP模式

Android开发之初识MVP模式

作者: 怡红快绿 | 来源:发表于2019-04-02 18:21 被阅读0次

    一、什么是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发送数据请求。
    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
    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<String, Object> 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模式

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