MVP就是Model-View-Presenter,MVP是从经典的模式MVC演变而来,它们的基本思想有想通的地方:Controller、Presenter负责逻辑的处理,Model提供数据,View负责显示。作为一种新的模式,MVC和MVP有着重大的区别:在MVP中View并不直接使用Model,它们之间的通信是通过Presenter来进行的,所有的交互都发生在Presenter内部,而在MVC中View会直接从Model中读取数据而不是通过Controller。
在MVC里,View是可以直接访问Model的,从而,View里会包含Model信息,不可避免的还要包括一些业务逻辑。在MVC模型里,更关注Model的不变,而同时有多个对Model的不同显示,及View。所以,在MVC模型里,Model不依赖与View,但是View是依赖于Model的。不仅如此,因为有一些业务逻辑在View里实现了,导致更改View也是比较困难的,至少那些业务逻辑是无法重用的。
MVP架构
View:对应于Activity,负责View的绘制以及与用户交互
Model:依然是业务逻辑和实体模型
Presenter:负责完成View与Model间的交互
MVP架构
View:对应于Activity,负责View的绘制以及与用户交互
Model:依然是业务逻辑和实体模型
Presenter:负责完成View与Model间的交互
View不直接与Model交互,而是通过与Presenter交互来与Model间接交互
Presenter与View的交互是通过接口来进行的
通常View与Presenter是一对一的,但复杂的View可能绑定多个Presenter来处理逻辑。
MVC架构:
View:对应于布局文件
Model:业务逻辑和实体模型
Controller:对应于Activity
总结一下就是说:从MVC到MVP的一个转变,就是减少了Activity的职责,减轻了它的负担,简化了Activity中的代码和一些操作,将逻辑代码提取到了Presenter中进行处理,降低了其耦合度
在MVP里,Presenter完全把Model和View进行了分离,主要的程序逻辑在Presenter里实现。而且,Presenter与具体的View是没有直接关联的,而是通过定义好的接口进行交互,从而使得在变更View时候可以保持Presenter的不变,即重用。不仅如此,我们还可以编写测试用的View,模拟用户的各种操作,从而实现对Presenter的测试-而不需要使用自动化测试工具。我们甚至可以在Model和View都没有完成的时候,就可以通过编写Mock Object(即实现了Model和View的接口,但没有具体内容的)来测试Presenter的逻辑。在MVP里,应用程序的逻辑主要在Presenter来实现,其中的View是很薄的一层。
MVP的优点
1.降低耦合度,隐藏数据,Activity中代码更简洁
2.模块职责划分明显
3.方便测试驱动开发
4.代码复用度较高
5.代码灵活
MVP小demo,包结构如下
Model层
首先是User的bean对象
package com.liuke.mvpdemo.model;
public class User {
private String name;
private String id;
private String sex;
private String age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
}<strong>
</strong>
Model层的两个抽象接口
OnUserInfoListener.java
package com.liuke.mvpdemo.model;
public interface OnUserInfoListener {
void getUserInfoSuccess(User user);
void getUserInfoFaled();
}
IGetUser.java
package com.liuke.mvpdemo.model;
public interface IGetUser {
void getUserInfo(int id,OnUserInfoListener listener);
}<strong>
</strong>
View层
package com.liuke.mvpdemo.view;
import com.liuke.mvpdemo.model.User;
public interface IShowUserView {
void showLoading();
void hideLoading();
void toMainActivity(User user);
void showFailedError();
}
Presenter层
UserInfoPresenter.javapackage com.liuke.mvpdemo.presenter;
import android.os.Handler;
import com.liuke.mvpdemo.bean.User;
import com.liuke.mvpdemo.model.IGetUser;
import com.liuke.mvpdemo.model.OnUserInfoListener;
import com.liuke.mvpdemo.view.IShowUserView;
public class UserInfoPresenter {
private IGetUser iGetUser;
private IShowUserView isShowUserView;
private Handler mHandler=new Handler();
public UserInfoPresenter(IGetUser iGetUser, IShowUserView isShowUserView) {
super();
this.iGetUser = iGetUser;
this.isShowUserView = isShowUserView;
}
public void getUserInfoToShow(int id){
isShowUserView.showLoading();
iGetUser.getUserInfo(id, new OnUserInfoListener() {
@Override
public void getUserInfoSuccess(final User user) {
// TODO Auto-generated method stub
mHandler.post(new Runnable() {
@Override
public void run() {
isShowUserView.toMainActivity(user);
isShowUserView.hideLoading();
}
});
}
@Override
public void getUserInfoFaled() {
isShowUserView.showFailedError();
isShowUserView.hideLoading();
}
});
}
}<strong>
</strong>
MainActivity.java
package com.liuke.mvpdemo;
import android.app.Activity;
import android.app.ProgressDialog;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import com.liuke.mvpdemo.bean.User;
import com.liuke.mvpdemo.presenter.UserInfoPresenter;
import com.liuke.mvpdemo.view.IShowUserView;
public class MainActivity extends Activity implements IShowUserView {
private UserInfoPresenter userInfoPresenter;
private TextView tv_name, tv_sex, tv_age;
private Button btn;
private ProgressDialog pd;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
userInfoPresenter = new UserInfoPresenter(this);
tv_name = (TextView) findViewById(R.id.tv_name);
tv_age = (TextView) findViewById(R.id.tv_age);
tv_sex = (TextView) findViewById(R.id.tv_sex);
btn=(Button) findViewById(R.id.button);
pd = new ProgressDialog(this);
pd.setMessage("正在加载...");
btn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
userInfoPresenter.getUserInfoToShow(1);
}
});
}
@Override
public void showLoading() {
pd.show();
}
@Override
public void hideLoading() {
pd.cancel();
}
@Override
public void toMainActivity(User user) {
tv_name.setText(user.getName());
tv_sex.setText(user.getSex());
tv_age.setText(user.getAge());
}
@Override
public void showFailedError() {
Toast.makeText(this, "获取信息有误", Toast.LENGTH_SHORT).show();
}
}