MVP

作者: Amy木婉清 | 来源:发表于2022-01-10 14:18 被阅读0次

    MVP耦合图示:

    image.png
    MVP使用交互流程图示:
    image.png
    MVP全称是Model-View-Presenter,是模型(model)-视图(view)-呈现器(Presenter)的缩写。
    Model:业务逻辑和数据处理(数据库存储操作,网络数据请求,复杂算法。耗时操作)
    View:对应与Activity,负责View的绘制以及与用户交互
    Presenter:负责完成View与Model间的交互(有一点还需注意,presenter是双向绑定的关系,因此,在设计的时候就要注意到接口和抽象的使用,尽可能的降低代码的耦合度,这也是mvp的宗旨)
    责任划分
    Model:定义并实现获取数据操作(如数据库读取、网络加载)的接口
    View:定义并在Activtiy、Fragment等中实现用于界面处理(初始化、数据展示)的接口
    Presenter:定义用于调用Model的数据请求方法的接口,实现此接口,并实现Model中定义的数据请求接口
    项目结构
    image.png
    Step 1、编写Model逻辑

    数据请求接口(如数据库读取、网络加载)的定义

      /**
         * Model层接口--实现该接口的类负责世界的数据获取操作,如数据库读取、网络加载
         */
    
        public interface IModel{
    
            void getData(Model.LoadDataCallback callback);
        }
    

    数据请求接口的实现

        /**
         * 实现IModel接口、负责实际的数据获取操作(数据库读取、网络加载等),然后通过自己的接口(LoadDataCallback)反馈出去
         */
    
        public class Model implements IModel{
    
            @Override
            public void getData(final LoadDataCallback callback) {
                //数据获取操作、如数据库查询、网络加载等
    
                new Thread(){
                    @Override
                    public void run() {
                        try {
                            //模拟耗时操作
                            Thread.sleep(3000);
                            //获取到了数据
                            String data="我是获取到的数据";
                            //将获取到的数据通过接口反馈出去
                            callback.success(data);
                        } catch (Exception e) {
                            e.printStackTrace();
                            //获取数据失败的回调
                            callback.failure();
                        }
                    }
                }.start();
            }
            /**
             * 用于回传请求的数据的回传
             */
    
            public interface  LoadDataCallback{
                void success(String taskId);
    
                void failure();
            }
        }
    
    Step2/编写View逻辑

    定义用于界面处理(初始化,数据展示)的接口

    /**
     * View层接口---执行各种UI操作,定义的方法主要是给Presenter中来调用的
     */
    public interface IView {
    
        void showLoadingProgress(String message);
    
        void showData(String text);
    }
    

    在Activtiy 、Fragment等中对接口的实现:

    /**
     * 实现IView接口并实现各种UI操作的方法(其他的业务逻辑在Presenter中进行操作)
     */
    public class ViewActivity extends AppCompatActivity implements IView {
    
        private Button mBtnShowToast;
        private TextView mText;
        private MyHandler mHandler = new MyHandler(ViewActivity.this);
        private IPresenter mPresenter;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_mvp);
    
            //实例化Presenter,并将实现了IView接口的类传入进去
            mPresenter = new Presenter(ViewActivity.this);
    
            mBtnShowToast = findViewById(R.id.btn_show_toast);
            mText = findViewById(R.id.text);
    
            mBtnShowToast.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    //通过Presenter来实现业务逻辑操作,View层只负责UI相关操作
                    mPresenter.loadData();
                }
            });
        }
    
        @Override
        public void showLoadingProgress(final String message) {
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    mText.setText(message);
                }
            });
        }
    
        @Override
        public void showData(final String text) {
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    mText.setText(text);
                }
            });
        }
    
        private static class MyHandler extends Handler {
    
            //弱引用,防止内存泄露
            WeakReference<ViewActivity> weakReference;
    
            public MyHandler(ViewActivity activity) {
                this.weakReference = new WeakReference<ViewActivity>(activity);
            }
    
            @Override
            public void handleMessage(Message msg) {
                switch (msg.what) {
                    case 1:
                        weakReference.get().mText.setText(msg.what);
                        break;
                }
            }
        }
    }
    
    Step3/编写Presenter逻辑(重点)

    presenter层很重要,因为MVP模式中,View和Model通过presenter纽带进行交互----
    View通过presenter对象来调用Model中数据请求的接口,而Model中数据请求的结果会通过presenter中定义的接口回调给presenter,然后在通过presenter通知给view

    定义用于调用Model中的数据请求方法的接口具体实现:

        /**
         * Presenter层接口--控制Model层的数据库操作及调用View层的UI操作来完成“中间人”工作
         */
    
        public interface IPresenter {
    
            void loadData();
        }
    

    定义用于调用Model中的数据请求方法的接口,实现此接口,并实现M中定义的数据请求的接口

    /**
     * Presenter层接口---控制Model层的数据操作及调用View层的UI操作来完成“中间人”工作.
     * 用于model和view的相关方法的调用
     */
    public class Presenter implements IPresenter, Model.LoadDataCallback {
    
        private final IView mView;
        private final Model mModel;
    
        public Presenter(IView view) {
            mView = view;
            mModel = new Model();
        }
    
        @Override
        public void loadData() {
            mView.showLoadingProgress("加载数据中");
            mModel.getData(Presenter.this);
        }
    
        @Override
        public void success(String data) {
            mView.showData(data);
        }
    
        @Override
        public void failure() {
    
        }
    }
    
    MVP与MVC区别
    MVC结构示意图
    image.png
    MVP结构示意图
    image.png
    MVP MVC区别
    1.Activity职责不同

    Activtiy在MVP中时View层,在MVC中是Controller层,这是MVC 和MVP很主要的一个区别,可以说Android从MVC转向MVP开发也主要是优化Activity的代码,避免Activtiy的代码臃肿庞大

    2.View层不同

    MVC的View层指的是XML布局文件或者是用Java自定义的View,MVP层的View是Activtiy或者Fragment。使用传统的MVC,其中的View对应的是各种Layout布局文件,但是这些布局文件中并不像web端那样强大,能做的事情非常有限。MVP的View层Activity在实际项目中,随着逻辑的复杂度越来越大,Activtiy臃肿的缺点仍然体现出来了,因为Activtiy中还是充满了大量与View层无关的代码,比如各种事件的处理派发,就如MVC中的那样View层和Controller代码耦合在一起。

    3.控制层不同。

    MVC控制层是Activtiy,或者是Fragment,Controller对应的是Activity,而Activity中又具有操作UI的功能,我们在实际的项目中也会有很多UI操作在这一层,也做了很多View中应该做的事情,当然Controller层Activity中包含应该做的事情,比如各种事件的派发回调,而且在一层中我们会根据时间再去调用Model层操作数据,所以这种MVC的方式在实际项目中,Activtiy所在的Controller是非常重要的,各层次之间的耦合情况也比较严重,不方便单元测试。MVP的控制层是Presenter,里面没有很多的实际东西,主要是做Model和View层的交互。

    4.关系链不同

    MVP中Model层与View层是没有关系的,彼此不会通讯和操作,Model与View的通讯都是Presenter层来传达的。但是在MVC中,Model和View是存在交互的。比如我们自定义的View空间里面肯定要使用Model的数据,View也要根据不同的Model数据做出不同的展现。在MVP中,接口就可以完成。

    5.适用范围不同

    在Android中,MVP和MVC都有自己的适用情况。使用MVP可以更好的解耦三大模块,模块之间比较清晰,也很方便使用MVP来组件化架构整体项目。在组件化的Module或者中间件我们可以使用MVC,Module或者中间件中不会存在很复杂的View层,使用MVC更加方便

    6.交互方式不同

    MVP通讯交互基本都是通过接口的,MVC中的通讯交互很多时候都是调用对象的方法

    7.实现方法不同

    MVC和MVP的Model几乎是一样的,都是处理数据,只要不在Activity或者Fragment中请求数据,其他的所有控制都放在Activity或者Fragment中,这样写基本就是MVC,但是容易造成Activtiy代码冗余。用MVP则需要写很多View和Presenter接口来实现模块之间的通讯,会增加很多类。

    相同点

    优点:
    降低耦合度
    模块职责画风明显
    利于测试驱动开发
    代码复用
    隐藏数据
    代码灵活性
    缺点:
    额外的代码复杂度及学习成本

    不同点:
    MVP模式:
    View不直接与Model交互,而是通过与Presenter交互来与Model间接交互
    Presenter与VView的交互是用过接口来进行的,更有利于添加单元测试
    通常View与Presenter是一对一的,但复杂的View可能绑定多个Presenter来处理逻辑,业务相似的时候也可以多个View共享一个Presenter
    MVC模式:
    View可以与Model直接交互
    Controller是基于行为的,并且可以被多个View共享
    Controller可以负责决定显示哪个View

    相关文章

      网友评论

        本文标题:MVP

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