MVP模式

来源:互联网 发布:ubuntu jdk rpm 编辑:程序博客网 时间:2024/04/24 10:45

一.使用背景


 

1.逻辑业务被塞到View中(Activity),使得View变的混乱

2.MVP可以分离显示层和逻辑层,他们之间通过接口进行通信,降低耦合

3.数据层(可能是本地数据库检索数据,远程服务器,或者被替换)

4.UI层(随着产品迭代,肯定会重新设计),如果View中混合着逻辑,那么UI变化导致我们修改新的View控件,就要到原来的View中抽离具体的业务逻辑


理想状态:同一份逻辑代码搭配不同的显示界面,因为他们之间并不依赖于具体,而是依赖抽象

 

对于一个可扩展,稳定的应用来说,我们需要定义分离各个层,主要UI业务逻辑层(mvp中放到P)数据层(M)


 

二.MVP模式的三个角色

1.Presenter---交互中间人

Presenter主要作为沟通ViewModel的桥梁,他从Model层获取数据后(4返回给View层(1

使得ViewModel之间没有耦合,也将业务逻辑从View角色上抽离出来

 

2.View----用户界面

View通常指的是Activity,Fragment或者某个View控件,它含有一个一个Presenter成员变量。通常View需要实现一个逻辑接口,将View上的操作转给Presenter进行实现(2,最后Presenter调用View逻辑接口将结果返回给View元素

 

3.Model----数据存储

对于一个结构化的App来说,Model角色主要是提供数据的存取功能,Presenter需要通过Model层存储,获取数据(3,4,简单的说,Model就是封装了数据库DAO或者网络获取数据的角色,或者两者方式都有的集合



三.MVP简单实现

//接口M

public interface ArticleModel {    public void saveArticles(List<Article> articles);    public void loadArticlesFromCache(DataListener<List<Article>> listener);}
//具体的M

public class ArticleModeImple implements ArticleModel {    List<Article> mCacheArticles = new LinkedList<>();    @Override    public void saveArticles(List<Article> articles) {        mCacheArticles.addAll(articles);    }    @Override    public void loadArticlesFromCache(DataListener<List<Article>> listener) {        listener.onComplete(mCacheArticles);    }}

//链接V跟P的接口

public interface  ArticleViewInterface {    public void  showArticles(List<Article> articles);//展示数据    public void showLoading();    public void hideLoading();}

//具体的V

public class MainActivity extends Activity implements ArticleViewInterface {    RecyclerView mRecycleView;    ProgressBar progressBar;    List<Article> mArticles = new LinkedList<Article>();    ArticleAdapter mAdapter;    ArticlePresenter mPresenter;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        //初始化控件        initViews();        //初始化请求队列        //....        //构建ArticlePresenter,与ArticleActity建立关联        mPresenter = new ArticlePresenter(this);        //请求文章数据        mPresenter.fetchArticles();    }    private void initViews() {        //省略代码        //....    }    @Override    public void showArticles(List<Article> result) {        mArticles.addAll(result);//更新数据源        mAdapter.notifyDataSetChanged();//更新UI    }    @Override    public void showLoading() {    }    @Override    public void hideLoading() {    }}




//具体的P(一般会有一个接口P)

/** *Presenter作为View和Model的中间人 * */public class ArticlePresenter {    //ArticleView接口,代表了View接口角色    ArticleViewInterface mArticleView;    //文章数据的Model,也就是Model角色    ArticleModel mArticleModel = new ArticleModeImple();    //从网络上获取文章的API    ArticleAPI mAriticleApi = new ArticleAPIImpl();    public ArticlePresenter(ArticleViewInterface mArticleView) {        this.mArticleView = mArticleView;    }    //获取文章,也就是我们的业务逻辑    public void fetchArticles(){        mArticleView.showLoading();        mAriticleApi.fetchArticles(new DataListener<List<Article>>(){            @Override            public void onComplete(List<Article> result) {                //数据加载完,调用View的showArticles函数将数据传递给View显示                mArticleView.showArticles(result);                mArticleView.hideLoading();                //存储到数据库                mArticleModel.saveArticles(result);            }        });    }    public void loadArticlesFromDB(){        mArticleModel.loadArticlesFromCache(new DataListener<List<Article>>() {            @Override            public void onComplete(List<Article> result) {                //从数据库加载                mArticleView.showArticles(result);            }        });    }}


通过这个用例可以看到,Presenter对于View是完全解耦的,

1.Presenter依赖的是ArticleViewInterface抽象,而不是具体的MainActivity这个类,因此当UI界面变化,只要新UI实现AriticleViewInterface以及相关的逻辑就可以跟Presenter用起来

2.Presenter将业务逻辑从MainActivity抽离出来,让MainActivity变得非常轻量级,MainActivity只要做一些View的初始化

3.MVP中的ViewModel不能直接通信,他们交互通过PresenterArticlePresenter中持有

ArticleViewInterface(抽象),还持有ArticleModel(抽象),这两个的具体实现可以轻易被替换

1 0