MVP的简单理解

来源:互联网 发布:php电商项目架构 编辑:程序博客网 时间:2024/05/19 16:47

首先什么是MVP?

MVP代表Model,View和Presenter。

  • View层负责处理用户事件和视图部分的展示。在Android中,它可能是Activity或者Fragment类。
  • Model层负责访问数据。数据可以是远端的Server API,本地数据库或者SharedPreference等。
  • Presenter层是连接(或适配)View和Model的桥梁。

我们为什么要使用MVP?

大家都会说是为了降低耦合,让代码更加的清晰。
下面这两张图,大家应该都很熟悉
MVC:

这里写图片描述

MVP:

这里写图片描述

这两张图最明显的区别就是view层和逻辑层是否有相关性。这就是MVP低耦合的主要体现。
我的理解就是MVP就是让View显示数据,这个数据要通过Model获取,但是View不和Model接触,而是让Presenter 连接两者处理。这里的Presenter 只是关联两者数据具体的处理,传递给view让view加载显示数据还是model自己处理

这里写图片描述

下面我们可以看一个demo理解。

基本的代码结构:

这里写图片描述
简单理解一下:

model:

IMainModel:处理数据的接口LoadDataListener:数据处理的回调接口MainModel:处理数据接口的实现类

presenter:

LoadPresenter:连接model和view

View

IMainVIew:view页面显示的接口MainActivity:view接口的实现类

首先我们要注意的,MVP中接口起着很大的作用。view显示要接口,数据逻辑处理还是通过接口。
现在我们先按照我们的demo来一步步理解,我们要做的是一个加载网络数据显示,然后点击加载更多的demo。
首先我们看View。这里要显示数据,我们可以用Listview,然后一个按钮点击加载更多。为了更加的用户化,我们可以加一些提示,比如加载成功,失败,也可以给一个加载等待的弹框,这里我们就简单一下,只用toast提示。那次是这个view的接口要有的方法就有:

public interface IMainVIew {    /**     * 提示     * @param content     */    void tip(String content);    /**     * 加载数据     */    void loadData(List<String> data);    /**     * 加载更多     */    void loadMore(List<String> data);    /**     获取参数     */    int getCount();    int getStart();}

MainActivity实现这个类,这里的数据是我自己写死的,一般情况都是从哪个地方传递过来或者在edittext中获取到的:

    @Override    public void tip(String content) {        Toast.makeText(this,content,Toast.LENGTH_LONG).show();    }    @Override    public int getCount() {        //应该是返回某一个view获取的输入值        return 10;    }    @Override    public int getStart() {        return 0;    }

然后来看看model层:

public interface IMainModel {    void loadMore(int start,int count,LoadDataListener listener);    void loadData(int start,int count,LoadDataListener listener);}

这里为什么有这两个方法大家也知道了吧。当然其实一个方法即加载数据又加载更多其实就够了,这里我就写了两个。既然model是数据逻辑层,那么它包含的就是数据相关的处理,从上面分析view层我们可以定义两个方法,一个loadData,一个loadMore。

然后是model的实现类

public class MainModel implements IMainModel{    @Override    public void loadMore(int start,int count, final LoadDataListener listener) {    }    @Override    public void loadData(int start,int count,final LoadDataListener listener) {    }}

这里的LoadDataListener就是数据处理的回调接口。

public interface LoadDataListener {    void  loadSuccess(List<String> data);    void  loadFaild(String log);}

这里的数据加载我就是简单的模拟一般请求,返回一个集合。
现在贴一下model中代码的具体处理:

 @Override    public void loadData(int start,int count,final LoadDataListener listener) {        Call<MovieEntity> loadMoreData = MyAPPlication.iRetrofitService.getData(start,count);        loadMoreData.enqueue(new Callback<MovieEntity>() {            @Override            public void onResponse(Response<MovieEntity> response, Retrofit retrofit) {                MovieEntity entity= response.body();                Log.i("yqy","加载成功"+entity.getCount()+"");                for (int i = 0; i < entity.getSubjects().size(); i++) {                    MovieEntity.SubjectsBean  subject=entity.getSubjects().get(i);                    data.add(subject.getTitle());                }                listener.loadSuccess(data);            }            @Override            public void onFailure(Throwable t) {                listener.loadFaild(t.getMessage());                Log.i("yqy",""+t.getMessage());            }        });    }

可以看到这里只是简单的模拟数据,后期会修改…..T_T
好了,现在model和view好了,最后就是presenter了。前面说了MVP中model和view是不直接联系的,这里的纽带就是presenter。那么presenter是怎么关联这两个的呢?
先看一下代码:

public class LoadPresenter {    private IMainVIew iMainVIew ;    private MainModel mainModel =new MainModel();    public LoadPresenter(IMainVIew iMainVIew) {        this.iMainVIew = iMainVIew;    }    //加载方法调用model的加载数据    public void loadData(){        mainModel.loadData(iMainVIew.getStart(),iMainVIew.getCount(), new LoadDataListener() {            @Override            public void loadSuccess(List<String> data) {                iMainVIew.tip("加载成功");                iMainVIew.loadData(data);            }            @Override            public void loadFaild(String log) {                iMainVIew.tip("加载失败"+log);            }        });    }    public void loadMore(){        mainModel.loadMore(iMainVIew.getStart(),iMainVIew.getCount(), new LoadDataListener() {            @Override            public void loadSuccess(List<String> data) {                iMainVIew.tip("加载more成功");                iMainVIew.loadData(data);            }            @Override            public void loadFaild(String log) {                iMainVIew.tip("加载more失败"+log);            }        });    }}

可以看到这里:

 private IMainVIew iMainVIew ; private MainModel mainModel =new MainModel(); public LoadPresenter(IMainVIew iMainVIew) {        this.iMainVIew = iMainVIew;    }

view层的接口是通过presenter 的构造函数初始化的,而model缺失通过自己new来初始化。这样你可以单独的测试数据是否获取成功,与其他不关联,就比如javaweb中的dao,你可可以直接对model执行单元测试,因为业务逻辑与视图层是分离的。

最后,我们再来看一下图:
这里写图片描述

这里我们view和presenter是双向的,presenter连接了view和model ,那view是怎么通知presenter显示数据的呢?
在presenter中我们定义了两个方法loadData(),loadMore();
这里的处理大家可以看到,就是model获取数据,view显示。所以在view(MainActivity)中,接口IMainView的loadData()方法中直接显示数据:

//关联presenter loadPresenter =new LoadPresenter(this); loadPresenter.loadData();
 @Override    public void loadData(List<String> data) {        datas=data;        adapter =new ArrayAdapter(this,android.R.layout.simple_list_item_1,datas);        listView.setAdapter(adapter);    }    @Override    public void loadMore(List<String> data) {        adapter.notifyDataSetChanged();    }

这里的data就是presenter中loadData()的:

    public void loadSuccess(List<String> data) {                iMainVIew.tip("加载more成功");                iMainVIew.loadData(data);      }

这个方法实现的。

总结:
View告知presenter要显示数据,presenter 提示model层“view要数据了,你麻溜处理”,model接收后处理数据,最后view来显示。这里我们注意的是presenter 只是纽带,不处理其他事情。model是数据处理,可以单元测试的独立模块。以上是我的理解整理,不对的欢迎大家指正感谢~

最终:
这里写图片描述
以上。

demo下载


参考:
http://blog.csdn.net/lmj623565791/article/details/46596109
http://www.codeceo.com/article/android-mvp-artch.html
http://www.bubuko.com/infodetail-800718.html

0 0
原创粉丝点击