MVP模式使用示例详解

什么是MVP模式?
     这个MVP可不是腾讯游戏《王者荣耀》中的MVP。我们今天要讨论的MVP其实同MVC一样,是一种编程模式和思想,也许更准确地讲是一种架构。

MVP和MVC的区别
     提到MVP模式,大家自然避免不了要和我们以前常用的MVC模式进行对比。关于MVP和MVC的区别,此处我们就不重复造轮子了,给大家推荐两篇文章:

两张图看懂Android开发中MVC与MVP的区别
Android中MVP模式讲解及实践

MVP模式的介绍
先上两张示例图(网上的图大同小异,都一样)

mvp耦合图示:

mvp使用交互流程图示: 

MVP 全称是Model - View - Presenter ,是模型(model)-视图(view)-呈现器(presenter)的缩写。

Model:业务逻辑和数据处理(数据库存储操作,网络数据请求,复杂算法,耗时操作)。

View : 对应于Activity,负责View的绘制以及与用户交互。

Presenter:负责完成View于Model间的交互 (有一点还需要注意,presenter是双向绑定的关系,因此,在设计的时候就要注意接口和抽象的使用,尽可能的降低代码的耦合度,这也是mvp的宗旨)。

MVP模式使用示例佐证
下面参照网上有个比较通俗的示例,来讲述下MVP 模式的使用。
以最常用的网络数据请求为例。
先来明确下MVP中各个环节的责任划分,然后照此进行代码布局。

责任划分:
Model: 定义并实现获取数据操作(如数据库读取、网络加载)的接口
View: 定义并在Activity,Fragment等中实现用于界面处理(初始化,数据展示)的接口
Presenter: 定义用于调用Model中的数据请求方法的接口,实现此接口,并实现Model中定义的数据请求的接口

项目结构:

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 (InterruptedException e) {
                    e.printStackTrace();
                    //获取数据失败的回调
                    callback.failure();
                }
            }
        }.start();
    }

    /**
     *
     * 用于回传请求的数据的回传
     */
    public interface LoadDataCallback {

        void success(String taskId);

        void failure();
    }
}

Step 2/编写View逻辑:
定义用于界面处理(初始化,数据展示)的接口
 

/**
 * View层接口---执行各种UI操作,定义的方法主要是给Presenter中来调用的
 */
public interface IView {

    void showLoadingProgress(String message);

    void showData(String text);
}

在Activity,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;
            }
        }
    }
}

Step 3/编写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() {

    }
}


大家要多看,多试验,最重要的是理解思路,理解思路,理解思路。重要的事情说三遍。Google官方的MVP代码大家可以去研读一下,是同一个模式,只不过它把好多接口集成在一个接口文件中,防止代码碎片化,大家研读时记住这一点,就不会困惑了。

最后附上Google MVP的代码地址:

https://github.com/googlesamples/android-architecture/tree/todo-mvp/


————————————————
版权声明:本文为CSDN博主「游走的大千世界的烤腰子」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/zhangqunshuai/article/details/82562801

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值