框架模式-MVP

什么是MVP

MVP是一种模型,是模型(Moudle)、视图(View)、主持人(Presenter)组成的。

  • 模型(Moudle):负责处理数据,比如网络的加载数据,本地存取数据。
  • 视图(View)负责界面展示,及与用户交互。
  • 主持人(Presenter)协调者,M与V的桥梁,负责把数据设置到
    View上。

MVP模式图:


这里写图片描述

如图所示,View与Model并不直接交互,而是由Presenter实现调用Model取得数据,再把数据给View,View拿到数据在进行展示。这里概念不多讲概念。

MVP的好处:

这样分层的好处就是大大减少了Model与View层之间的耦合度。一方面可以使得View层和Model层单独开发与测试,互不依赖。另一方面Model层可以封装复用,可以极大的减少代码量。当然,MVP还有其他的一些优点,这里不再赘述。下面看下MVP模式在具体项目中的使用。

假设没有MVP,也没有MVC,现在要实现这种视图(V)和数据(M)的分离,应该怎么去做?这个时候会用到P(中间人)来负责拿取M,然后在传递给V。

V->P 在V视图里取得P的事例,调用P的方法,去获取数据。
对应代码应该这么写:

//这里已加载一个新闻为例,给P取名为NewsPresenter
NewsPresenter presenter=new NewsPresenter();
//在NewPresenter定义的加载数据的方法,里面调用Moudle,去加载数据
presenter.loadDatas();

为了让P更好的扩展,给P定义一个接口,由P去实现这个接口,
代码应该这么写:

public interface NewsPresenter {
    //参数根据加载数据的需求选填
    void loadDatas(int type, int pageIndex);
}

//P该这么写:
public class NewsPresenterImp implements NewsPresenter {
    @Override
    public void loadDatas(int type, int pageIndex) {
       //这里负责调用M,去加载数据
    }
}

在P中调用M去获得数据,在把数据设置到V上,应该怎么做?
代码应该这么写:

public NewsPresenterImp(NewsView newsView){
        //在V 获取P的实例时,把V的实例对象传递给P
        this.mView=newsView;
        //M和上面的P一样,同样让它实现一个接口,这样容易扩展
        mMoudle=new NewsMoudleImp();
    }

定义一个M的接口,让M去实现这个接口:

public interface NewsMoudle {
//这里OnLoadListerner是一个监听返回接口
    void loadNewsDatas(String url,int type,OnLoadListener onLoadListener);
}

对应NewsMoudleImp实现类:

public class NewsMoudleImp implements NewsMoudle {
    @Override
    public void loadNewsDatas(String url, int type, final OnLoadListener onLoadListener) {
        OkHttpUtils.ResultCallback<String> callback= new OkHttpUtils.ResultCallback<String>() {
            @Override
            public void onSuccess(String response) {
                //网络操作部分获取数据,这里可以忽略
                List<NewsEntity> newsBeanList = NewsJsonUtils.readJsonNewsBeans(response, Urls.TOP_ID);
                //成功调取监听成功的方法
                onLoadListener.onSucceed(newsBeanList);
            }

            @Override
            public void onFailure(Exception e) {
                //失败调取监听失败的方法
                onLoadListener.onFailure("加载失败");
            }
        };

        OkHttpUtils.get(url,callback);
    }

对应监听接口的:

public interface OnLoadListener {
    void onSucceed( List<NewsEntity> datas);
    void onFailure(String msg);

}

这个时候,在P的实现类NewsPresenterImp里的loadDatas这么写:

 @Override
    public void loadDatas(int type, int pageIndex) {
        String url = getUrl(type, pageIndex);
        mMoudle.loadNewsDatas(url, type, new OnLoadListener() {
            @Override
            public void onSucceed(List<NewsEntity> datas) {
                mView.showData(datas); //这里mView就是V的实例引用
                mView.hideProgress();
            }

            @Override
            public void onFailure(String msg) {
                mView.showFailMsg(msg);
                mView.hideProgress();
            }
        });
    }

写到这里,一个流程就走通了,首先是在V中,一般V我们都是指acitivty、Fragment,在这里new一个P的实例,让P去调用M的实例去加载数据,也就是上面的代码,M取得数据后,不管成功或着失败,都把这个结果返回交给P,最后由P去处理这个结果,把处理的结果,给V,也就是mView这个V的引用,从而实现MVP这一整套逻辑。

看V,也同样实现一个接口,这里给它取名NewsView,对应代码:

public interface NewsView {
    //展示数据
    void showData(List<NewsEntity> newsDatas);
    //显示度条
    void showProgress();
    //隐藏进度条
    void hideProgress();
    //获取数据失败时,返回的信息
    void showFailMsg(String msg);
}

V去实现这个V的接口,代码这样写:

ublic class MainActivity extends AppCompatActivity implements NewsView, SwipeRefreshLayout.OnRefreshListener {
    private NewsPresenterImp presenter;
    private String urlPath = "";
    private List<NewsEntity> mData;
    private int mType = 0;
    private int pageIndex = 0;
    private SwipeRefreshLayout swipeRefreshLayout;
    private RecyclerView recycleView;
    private NewsAdapter mAdapter = null;
    private LinearLayoutManager mLayoutManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
        initDatas();
    }

    private void initView() {
        swipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.swiperefreshlayout);
        swipeRefreshLayout.setOnRefreshListener(this);
        recycleView = (RecyclerView) findViewById(R.id.recyclerview);
        recycleView.setHasFixedSize(true);
        mLayoutManager = new LinearLayoutManager(this);
        recycleView.setLayoutManager(mLayoutManager);
        recycleView.setItemAnimator(new DefaultItemAnimator());
        mAdapter = new NewsAdapter(this);

    }

    private void initDatas() {
        //这里重点,获取P的实例,让P去调用Moudle的实例加载数据
        presenter = new NewsPresenterImp(this);
        presenter.loadDatas(mType, pageIndex + Urls.PAZE_SIZE);


    }

    @Override
    public void showData(List<NewsEntity> newsDatas) {
        //数据获取成功后,在P中V的引用mView调取这个方法,得到数据
    }

    @Override
    public void showProgress() {
        //显示进度条
    }

    @Override
    public void hideProgress() {
       //隐藏进度条
    }

    @Override
    public void showFailMsg(String msg) {
        Toast.makeText(MainActivity.this, "msg", Toast.LENGTH_SHORT).show();
    }
}

结论:整个逻辑就这样,仔仔细细看几遍,动手敲敲,会发现很清晰,就到这里了,代码例子时参考下面的例子写的,有问题就拍砖,欢迎多多指教~~

转载请表明:http://blog.csdn.net/zxyudia/article/details/63324063

上面事例demo下载点击这里,下面的博客demo会更好点

参考这里,讲的和demo都很好,demo下有好几个mvp例子,何妨一看

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值