各部分之间的通信,都是双向的。
View 与 Model 不发生联系,都通过 Presenter 传递。
View 非常薄,不部署任何业务逻辑,称为"被动视图"(Passive View),即没有任何主动性,而 Presenter非常厚,所有逻辑都部署在那里。
在Android中使用MVP框架
View 对应于Activity,负责View的绘制以及与用户交互
Model 依然是业务逻辑和实体模型
Presenter 负责完成View于Model间的交互
MVP框架的简单demo
1.实体类(属于Model层)
public class UserBean {
private String mFirstName;
private String mLastName;
public UserBean(String firstName, String lastName) {
this.mFirstName = firstName;
this.mLastName = lastName;
}
public String getFirstName() {
return mFirstName;
}
public String getLastName() {
return mLastName;
}
}
- View层接口
public interface IUserView {
/*
View层,对ID,FirstName,LastName
这三个EditText进行读操作
*/
int getID();
String getFristName();
String getLastName();
/*
对FirstName,LastName
进行写操作(根据ID,获得FirstName,LastName,并显示出来)
*/
void setFirstName(String firstName);
void setLastName(String lastName);
}
- 实现View层接口,在Android中通常是Activity实现的
public class UserActivity extends AppCompatActivity implements
View.OnClickListener, IUserView {
private EditText mFirstNameEditText, mLastNameEditText, mIdEditText;
private Button mSaveButton, mLoadButton;
private UserPresenter mUserPresenter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_user);
findWidgets();
//实例化一个 Presenter的对象
mUserPresenter = new UserPresenter(this);
mSaveButton.setOnClickListener(this);
mLoadButton.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.saveButton:
mUserPresenter.saveUser(getID(), getFristName(),
getLastName());
break;
case R.id.loadButton:
mUserPresenter.loadUser(getID());
break;
default:
break;
}
}
@Override
public void setFirstName(String firstName) {
mFirstNameEditText.setText(firstName);
}
@Override
public void setLastName(String lastName) {
mLastNameEditText.setText(lastName);
}
@Override
public int getID() {
return Integer.parseInt(mIdEditText.getText().toString());
}
@Override
public String getFristName() {
return mFirstNameEditText.getText().toString();
}
@Override
public String getLastName() {
return mLastNameEditText.getText().toString();
}
void findWidgets() {
mFirstNameEditText = (EditText) findViewById(R.id.first_name_edt);
mLastNameEditText = (EditText) findViewById(R.id.last_name_edt);
mIdEditText = (EditText) findViewById(R.id.id_edt);
mSaveButton = (Button) findViewById(R.id.saveButton);
mLoadButton = (Button) findViewById(R.id.loadButton);
}
}
附:
实例化一个Present的对象,传入Activity。 Activity通过接口与Presenter进行互动, 这样可以降低耦合
- Present层,作为V层和M层的联系。
public class UserPresenter {
private IUserView mUserView; //视图View层的接口实例
private IUserModel mUserModel; //模型Model层的接口实例
public UserPresenter(IUserView view) {
mUserView = view;
mUserModel = new UserModel();
}
/*
保存view层看到的数据的处理逻辑放在Presenter 里面实现
但实际是调用模型Model的接口,把操作交付给Model层去处理实现。
*/
public void saveUser(int id, String firstName, String lastName) {
mUserModel.setID(id);
mUserModel.setFirstName(firstName);
mUserModel.setLastName(lastName);
}
/**
* 在Presenter中调用Model处理完数据后
* 通过IUserView更新View显示的信息
* @param id
*/
public void loadUser(int id) {
UserBean user = mUserModel.load(id);
mUserView.setFirstName(user.getFirstName());
mUserView.setLastName(user.getLastName());
}
}
附:
1.Present层都是通过接口进行互动,可以降低耦合
2.Present层的构造方法通常传入View接口对象,构造Model接口对象。
3.保存view层看到的数据的处理逻辑放在Presenter 里面实现,但实际是调用模型Model的接口,把操作交付给Model层去处理实现。体现了Present层只是V层和M层的联系。
5.Model接口层
public interface IUserModel {
/*
在Model层对三个字段进行写操作
*/
void setID(int id);
void setFirstName(String firstName);
void setLastName(String lastName);
/*
在Model层根据ID读取数据:FirstName,LastName
返回一个UserBean 对象实体
*/
UserBean load(int id);
}
6.实现Model接口层
public class UserModel implements IUserModel{
@Override
public void setID(int id) {
}
@Override
public void setFirstName(String firstName) {
}
@Override
public void setLastName(String lastName) {
}
@Override
public UserBean load(int id) {
return null;
}
}
附:
负责数据的存储、检索、操作,具体逻辑没有详细列出。
MVP模式的优点:
1.MVP模式会解除View与Model的耦合,有效的降低View的复杂性。同时又带来了良好的可扩展性、可测试性,保证系统的整洁性和灵活性。
在MVP模式中,处理复杂逻辑的Presenter是通过interface与View(Activity)进行交互的,这说明了什么?说明我们可以通过自定义类实现这个interface来模拟Activity的行为对Presenter进行单元测试,省去了大量的部署及测试的时间。
MVP模式的缺点:
1.每一个View都需要连接一个Present,容易造成类数量爆炸,代码复杂度和学习成本高,在某些场景下presenter的复用会产生接口冗余。实际工作中没法抽象使得presenter重用。有时候业务简单就直接一个Activity搞定了。