转载请注明本文出自远古大钟的博客(http://blog.csdn.net/duo2005duo),谢谢支持!

简介

MVP是MVC的衍生版本,跟MVC类似,但是在Android中更适用,也分三层:
Android框架模式(1)-MVP入门_第1张图片
Model:用于数据的增删改查等,也包括一些数据对象
View:用于界面的显示与用户操作的接收,在Android里面View通常就是Actvitiy,Fragment。
Presenter:是View跟Model的“中间人”,接收View的请求后,从Model获取数据交给View。

MVP&MVC

传统MVC有着悠久的历史,但是Android却选用MVP,这绝非偶然。
在MVC中:
M:解决用什么去渲染
V:解决怎么去渲染
C:解决用户输入事件

在Android中,假如使用MVC,代表V的layout资源并不能完全解决怎么去渲染的问题,还需要Activity的辅助,所以Activity也必然要代表V;但是同时,Activity一方面拥有生命周期回调,另外一方面还为View设置监听,Activity接收来自用户的输入,所以Activity也必然也代表C,Activity就像一个万能对象同时代表着V与C。因此,使用MVC并不能很好地将V与C分离开来。
与MVC不同的是,MVP中的View是可以接收用户输入,同时也能解决怎么去渲染的问题,所以Activity可以作为MVP里面的View,但是却做不了MVC里面的View。因此,MVP更适用于Android。
但是View的改变不只在此:View在一方面增加了接收事件的责任,又在另一方面减少了操作Model的责任。View不再直接操作Model,只能通过Presenter去Model操作数据。可以说,MVC中的View与Control交换了部分工作,就成了现在的MVP。

实现

下面的例子是一个按下按钮后在TextView显示”helloworld from presenter“的例子

//View的接口public interface IView{    //1     void setData(String data);}//View的实现public class View extends Activity implements IView{    private IPresenter presenter;    private Button button;    private TextView text;    public void onCreate(Bundle args){        ....        presenter=new Presenter(this); //2 Presenter初始化        presenter.onCreate();   //3 将生命周期回调传给Presenter        button.setOnClickListener(new OnClickListener(){            public void onClick(View v){                presenter.performOnClick(); //4 用户输入            }        });    }    @override    public void setData(String data){           runOnUiThread(new Runnable(){     //ugly                public void run(){                    text.setText(data);                }            }        );    }} 

以上MVP中View层的实现。
(1)上面代码1处为View定制接口,接口中是给View设置数据的setData(String data)方法。View虽然不直接操作Model,但是这并不意味着View不跟数据打交道,相反,View需要数据来渲染自己。
(2)代码2位置初始化Presenter,Presenter模块是在View中初始化的,同时View还将自己传给Presenter。假设不给View,Presenter写对应的接口,Presenter将依赖View,View也将依赖Presenter,双向依赖是一种错误的设计,所以View,Presenter都有对应的接口,实现依赖倒置。
(3,4)在View中有两种情况需要调用Presenter,一种如代码3位置,View的生命周期回调中使用Presenter;另外一种如代码4位置,用户输入时使用Presenter。

//Presenter的接口public interface IPresenter{  //5     void onCreate();    void performOnClick();}//Presenter的实现public class Presenter implements IPresenter{    private IView view;   //6 拥有View与Model    private IModel model;     public Presenter(View view){           this.view=view;        model=new Model();    }    @override    public void onCreate(){        ...    }    @override    public void performOnClick(){        execute(new Runnable(){            public void run(){             //ugly                model.getData(new ICallback(){    //7 传接口给Model                    public void onResult(String data){                        String dataFromPresenter=data+" from presenter"; //8 加工数据                        view.setData(dataFromPresenter);                    }                });            }        };    }}

以上是Presenter层的实现
(5)代码5位置实现了Presenter接口,Presenter接口里面就是上文说的生命周期回调和用户输入,生命周期回调里面包含了对Presenter中资源初始化和释放;用户操作后,Presenter将数据加工后给View
(6)代码6位置可以知道Presenter不止依赖了View接口,也依赖了Model接口,可以说Presenter就像中介者模式中的Mediator
(7)代码7可以知道Presenter从Model获取数据,通常是用观察者模式来获取,因为获取数据一般是耗时操作,无法直接返回数据。
(8)代码8可以知道Presenter并不只是做数据的中转站,更重要的是Presenter还做数据的加工。让原始数据适合View的需要,这时候Presenter又有点像适配器模式中的adapter了,只是adapter是接口转换,Presenter这里是数据转换或者实体转换。

//Model接口public interface IModel{            //9 内嵌ICallback接口    void getData(ICallback callback);    public interface ICallBack{            public void onResult(String data);    }}//Model实现public class Model implements IModel{    void getData(ICallback callback){        ... //这里是耗时操作        callback.onResult("hello world");    //10 返回数据    }}

以上是Model层的代码,
(9)中不止定义了Model的接口,还定义了回调接口
(10)中经过了一系列耗时操作,最终回调callback,之后”hello world”数据传到Presenter,经过Presenter加工再传给View

让我们在回顾一下整个流程:

Created with Raphaël 2.1.0 User User View View Presenter Presenter Model Model Callback Callback onClick() performOnClick() getData(persenter.callback) onResult(data) setData(data)

整个流程中,你需要注意的是View,Presenter,Model是怎么创建出来的,从哪里创建出来,每个层间是如何交互的,分别有哪些接口需要定义。如果你还不清楚,请再回顾前文。

后续

掌握了本文所讲的内容也并不能说掌握了MVP,接下来的文章会介绍MVP中的细节与误区,还会介绍另外一种类似MVP并且更适于大型的工程的框架模式。

更多相关文章

  1. Android连接SQLServer详细教程(数据库+服务器+客户端),并在微软Azur
  2. Android数据库操作--greenDAO的入门使用
  3. Android 匿名共享内存C接口分析
  4. Android 高手进阶教程(十三)之----Android 数据库SQLiteDatabase
  5. 如何在自己的程序中添加appWidget(附简单代码)
  6. Android中WebView拦截替换网络请求数据
  7. Android两行代码真正杀死你的App

随机推荐

  1. Android(安卓)5.0之后隐式声明Intent 启
  2. 在Android上使用OpenCL调用GPU加速
  3. Android提高第九篇之SQLite分页表格[转]
  4. Android(安卓)LruCache技术原理
  5. 不用线程做Android软件欢迎界面,透明效果
  6. Android(安卓)For JNI(六)——交叉编译,ND
  7. Android(安卓)下枚举型使用、及与 int 转
  8. Android菜单设计(2) : options menu使用
  9. Android堆内存也可自己定义大小
  10. Facebook开源项目:我们为什么要用Fresco框