http://www.cnblogs.com/wanqieddy/p/4478690.html
上面有个例子,重点参考
http://www.cnblogs.com/mybkn/archive/2012/04/12/2443676.html
http://www.cnblogs.com/cqumonk/p/4392285.html
目录
一、MVP的介绍
二、为什么要用MVP
三、MVP与MVC的不同
四、利用MVP进行Android开发的例子
一、MVP的介绍
随着UI创建技术的功能越来越强,UI层也履行着越来越多的职责。为了更好的细分视图(View)与模型(Model)的功能,让View更专注于数据的可视化
和与用户的交互,同时让Model只关系数据的处理,基于MVC概念的MVP模式产生了。
MVP有下面的四个要素:
1.View:负责绘制UI元素,与用户进行交互,在Android中体现为Activity。
2.View interface:需要View实现的接口,View通过View interface 与 Presenter进行交互,降低耦合,方便进行单元测试。
3.Model: 负责存储,检索,操纵数据(有时也实现 一个Model interface用来降低耦合)。
4.Presenter:作为View 与 Model交互的中间纽带,处理与用户交互的逻辑。
如下图
二、为什么要用MVP
随着界面和逻辑的复杂度不断提升,Activity类的职责越来越重。因此我们将其中复杂的逻辑处理移到另外的一个类(Presenter)中时,Activit其实就是MVP
中的View ,它负责UI元素的初始化,建立UI元素与Presenter的关系(Listener之类),同时自己也会处理一些简单的逻辑(复杂的逻辑交由Presenter处理)。
另外,回想一下我们在开发android应用的时候,都是怎么对代码 逻辑进行测试的?每次我们都要将应用安装到android真机上,然后通过用户操作进行测试,
这浪费了我们大量的时间。而在MVP模式中,处理复杂逻辑的Presenter是通过 interface 与 View(Activity)进行交互的,所以我们可以通过自定义类实现这个
interface来模拟Activity 的行为对 Presenter进行单元测试,节省了大量的测试时间。
三、MVP与MVC的不同
MVP
- View 不直接与Model进行交互,而是通过与 Presenter 交互来与Model 间接交互。
- Presenter 与View的交互是通过接口来实现 的,利于添加单元测试。
- 通常View 与 Presenter 是一对一的,但复杂的View可以有多个 Presenter 。
MVC
- View可以与Model直接交互。
- Controller 是基于行为的,并且可以被多个View共享 。
- 可以负责决定显示哪个View
四、利用MVP进行Android开发的例子
首先是目录结构
可以看到Model与 View都是通过 interface与Presenter进行交互的,这样降低了耦合,还降低了测试的难度。
- 定义一个UserBean来保存用户信息
package com.chuiyuan.bean;
public class UserBean {
private String firstName ;
private String lastName ;
public UserBean (String firstName , String lastName ){
this.firstName = firstName ;
this.lastName = lastName ;
}
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
}
- View接口
由需求可以知道,View可以对ID ,firstname ,lastname这三个 EditText进行读操作,对firstname ,lastname 还可以进行写操作,由此我们定义接口如下
public interface IUserView {
int getID();
String getLastName () ;
String getFirstName ();
void setFirstName (String firstName );
void setLastName (String lastName ) ;
}
- Model接口
同样,Model也要对这三个字段进行读写操作,并存储在某个载体内(这时我们暂时不关心,可以是内存,文件,数据结构等,但对于Presenter和View没有
影响),定义 IUserModel的接口
public interface IUserModel {
void setID(int id ) ;
void setFirstName(String firstName );
void setLastName (String lastName);
UserBean load(int id ) ;//通过id读取信息
}
- Model功能的实现
public class UserModel implements IUserModel {
private String mFristName;
private String mLastName;
private int mID;
private SparseArray<UserBean> mUsererArray = new SparseArray<UserBean>();
@Override
public void setID(int id) {
// TODO Auto-generated method stub
mID = id;
}
@Override
public void setFirstName(String firstName) {
// TODO Auto-generated method stub
mFristName = firstName;
}
@Override
public void setLastName(String lastName) {
// TODO Auto-generated method stub
mLastName = lastName;
UserBean UserBean = new UserBean(mFristName, mLastName);
mUsererArray.append(mID, UserBean);
}
@Override
public UserBean load(int id) {
// TODO Auto-generated method stub
mID = id;
UserBean userBean = mUsererArray.get(mID, new UserBean("not found",
"not found"));
return userBean;
}
}
- Presenter
这时,Presenter就可以通过接口与Model/View进行交互了。
public class UserPresenter {
private IUserView mUserView ;
private IUserModel mUserModel ;
public UserPresenter (IUserView view){
mUserView = view ;
mUserModel = new UserModel();
}
public void saveUser (int id, String firstName ,String lastName ){
mUserModel.setID(id) ;
mUserModel.setFirstName(firstName) ;
mUserModel.setLastName(lastName) ;
}
public void loadUser (int id ){ //加载并更新显示
UserBean user = mUserModel.load(id) ;
mUserView.setFirstName(user.getFirstName()) ;
mUserView.setLastName(user.getLastName()) ;
}
}
- UserViewActivity
UserViewActivity实现了IUserView及View.OnClickListener接口,同时有一个UserPresenter成员变量.
package com.chuiyuan.view;
import com.chuiyuan.presenter.UserPresenter;
import com.example.mvptest.R;
import com.example.mvptest.R.id;
import com.example.mvptest.R.layout;
import android.R.integer;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
public class UserViewActivity extends ActionBarActivity implements OnClickListener, IUserView {
private EditText mFirstNameEt , mLastNameEt, mIdEt ;
private Button mSaveBtn ,mLoadBtn ;
private UserPresenter mUserPresenter ;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findWidget();
mUserPresenter = new UserPresenter(this ) ;
mSaveBtn.setOnClickListener(this ) ;
mLoadBtn.setOnClickListener(this );
}
private void findWidget() {
mFirstNameEt = (EditText)findViewById(R.id.first_name_edt);
mLastNameEt = (EditText)findViewById(R.id.last_name_edt) ;
mIdEt = (EditText)findViewById(R.id.id_edt ) ;
mSaveBtn = (Button)findViewById(R.id.saveButton) ;
mLoadBtn= (Button)findViewById(R.id.loadButton) ;
}
@Override
public int getID() {
// TODO Auto-generated method stub
return Integer.parseInt(mIdEt.getText().toString());
}
@Override
public String getLastName() {
// TODO Auto-generated method stub
return mLastNameEt.getText().toString();
}
@Override
public String getFirstName() {
// TODO Auto-generated method stub
return mFirstNameEt.getText().toString();
}
@Override
public void setFirstName(String firstName) {
mFirstNameEt.setText(firstName) ;
}
@Override
public void setLastName(String lastName) {
mLastNameEt.setText(lastName) ;
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.saveButton:
mUserPresenter.saveUser(getID(),
getFirstName(), getLastName()) ;
break;
case R.id.loadButton:
mUserPresenter.loadUser(getID()) ;
break ;
default:
break;
}
}
}
可以看到,View只负责处理与用户的交互,而将数据相关的逻辑都交给了Presenter去做,而Presenter调用Model处理完数据后,而通过IUserView更新
View的显示的消息。
整体结构如下