MVP基本概念
MVP(Model-View-Presenter)是从MVC的演变过来的,MVP的角色定义:
- 模型层(Model):主要是获取数据功能,业务逻辑和实体模型。
- 视图层(View):对应于Activity或Fragment,负责视图的部分展示和业务逻辑用户交互
- 控制层(Presenter):负责完成View层与Model层间的交互,通过P层来获取M层中数据后返回给V层,使得V层与M层间没有耦合。
在MVP中 ,Presenter层完全将View层和Model层进行了分离,把主要程序逻辑放在Presenter层实现,Presenter与具体的View层(Activity)是没有直接的关联,是通过定义接口来进行交互的,从而使得当View层(Activity)发生改变时,Persenter依然可以保持不变。View层接口类只应该只有set/get方法,及一些界面显示内容和用户输入,除此之外不应该有多余的内容。绝不允许View层直接访问Model层,这是与MVC最大区别之处,也是MVP核心优点。
MVP基本使用
项目目录结构主要分为三部分,分别是:model、view、presenter;其中model目录存放bean类、网络异步访问的接口及实现类和网络访问的回调接口,view目录对应的是Activity和View层接口,presenter层:对应的是presenter类。下面以一个简单的登录例子:
Model层:和MVC中M层是一样的,主要是定义网络请求接口(LoginModel)并实现接口(LoginModelImpl )然后通过接口的回调(LoginListener)把数据结果返回给P层,从而达到M层与V层间没有交互,是通过P层把结果返回给V层的,这与MVC是有所不同的是,在MVC中会直接把M层的数据返回到V层。
/**
* desc: 用户信息实体类
*/
public class UserInfo {
private String userName;
private String sex;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
}
/**
* desc:Login数据层的实现类
*/
public class LoginModelImpl implements LoginModel<UserInfo>{
@Override
public void getUserInfo(String userName, String pwd, LoginListener<UserInfo> listener) {
UserInfo userInfo = new UserInfo();
userInfo.setUserName(userName);
//下面是模拟网络访问结果的调用
listener.onStart_();
if (!TextUtils.isEmpty(userName) && !TextUtils.isEmpty(pwd)){
listener.onSuccess(userInfo);
}else {
listener.onFailed();
}
listener.onFinish();
}
}
/**
* desc: login-Model
*/
public interface LoginModel<T>{
void getUserInfo(String userName, String pwd, LoginListener<T> listener);
}
/**
* desc:登录回调监听
*/
public interface LoginListener<T> {
/*请求前一些准备,比如加载提示等待*/
void onStart_();
/*访问成功调用*/
void onSuccess(T t);
/*访问失败*/
void onFailed();
/*访问结束*/
void onFinish();
}
Presenter层:在Presenter类中有Model层和View层接口的实例,必须初始化了这两个实例才可以调用getUserData方法达到V层与M层的数据交互。
/**
* desc: Presenter层,通过P层来获取M层的数据,同时把数据返回给V层
* P层相当于V层与M层间中间桥梁,两者间的交互必须通过P层来完成
* 不允许直接访问。
*/
public class LoginPresenter {
private LoginModelImpl mLoginModel;
private LoginView<UserInfo> mLoginView;
public LoginPresenter(LoginModelImpl loginModel, LoginView<UserInfo> loginView) {
mLoginModel = loginModel;
mLoginView = loginView;
}
public void getUserData(String userName,String pwd){
mLoginModel.getUserInfo(userName, pwd, new LoginListener<UserInfo>() {
@Override
public void onStart_() {
mLoginView.showLoading();
}
@Override
public void onSuccess(UserInfo userInfo) {
mLoginView.showLoginSuccess(userInfo);
}
@Override
public void onFailed() {
mLoginView.showLoginFailed();
}
@Override
public void onFinish() {
mLoginView.hideLoading();
}
});
}
}
View层:V层是不能直接与M层进行交互的,必须通过接口的方式实现交互。
/**
* desc:定义View层接口,实现与Presenter层间交互
*/
public interface LoginView<T> {
/*显示dialog*/
void showLoading();
/*隐藏dialog*/
void hideLoading();
/*登录成功的处理操作,比如保存用户信息,跳转界面……*/
void showLoginSuccess(T t);
/*登录失败的提示*/
void showLoginFailed();
}
public class MainActivity extends AppCompatActivity implements LoginView<UserInfo> {
private EditText mEtName;
private EditText mEtPassword;
private Button mButLogin;
private ProgressDialog mProgressDialog;
private LoginModelImpl mLoginModel;
private LoginPresenter mLoginPresenter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mEtName = findViewById(R.id.et_user_name);
mEtPassword = findViewById(R.id.et_password);
mButLogin = findViewById(R.id.but_login);
mProgressDialog=new ProgressDialog(this);
mProgressDialog.setTitle("请求中……");
//
mLoginModel= new LoginModelImpl();
mLoginPresenter=new LoginPresenter(mLoginModel,this);
mButLogin.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//登录
String userName = mEtName.getText().toString();
String pwd = mEtPassword.getText().toString();
mLoginPresenter.getUserData(userName,pwd);
}
});
}
@Override
public void showLoading() {
Log.d(TAG, "showLoading: ");
mProgressDialog.show();
}
@Override
public void hideLoading() {
Log.d(TAG, "hideLoading: ");
mProgressDialog.dismiss();
}
@Override
public void showLoginSuccess(UserInfo userInfo) {
Log.d(TAG, "showLoginSuccess: ");
Toast.makeText(this,"登录成功",Toast.LENGTH_SHORT).show();
}
@Override
public void showLoginFailed() {
Log.d(TAG, "showLoginFailed: ");
Toast.makeText(this,"登录失败",Toast.LENGTH_SHORT).show();
}
private static final String TAG = "MainActivity";
}
总结:
MVP框架模式完全将Model模型和View视图分离,从而使得代码的耦合低,利用MVP框架写项目达到解耦作用。 MVP和MVC最大的区别是:MVC中的V和C关系比较紧密,耦合度太高,从C中访问M获取数据一定程度上也可以看成从V中访问M。而MVP中M和V完全分离,互相不知道对方的存在,Presenter通过接口通信方式将V和M通信。 在Android中MVP框架 Activity担当View视图层,MVC框架模式Activity担当控制器。
Android架构设计之MVC模式