Android架构模式详解之MVP
MVP概念
MVP 架构是由 MVC 演变而来的,而 MVP 架构的变化是由 Presenter 来负责业务逻辑。
Presenter 层作为 Model 层和 View 层的桥梁,来实现两者的交互。Model 层依然负责的是业务逻辑和数据模型,View 层负责界面绘制和用户的交互(接受用户输入,显示请求结果)和动效等的“单一职责”。
对比MVC
先回顾下上篇文章的 Android架构模式详解之MVC 的主要内容 。
Model 用于处理数据,业务逻辑等,若数据发生变化会直接通知 View 进行改变;
View 处理 UI 的显示,动效等等;
Controller 控制 Model 的请求,获得 View 的数据返回显示,作为 View 和 Model 的桥梁分离业务逻辑和 UI 显示。
MVP 模式使得 Model 层和 View 层实现了完全解耦。View 并不直接使用 Model,它们之间的通信是通过 Presenter(MVC 中的 Controller)来进行的,所有的交互都发生在 Presenter 内部,而在 MVC 中 View 会直接从 Model 中读取数据而不是通过 Controller。
同时 Presenter 可以多次重用,方便了业务逻辑的测试。但也存在一些缺点,由于 Presenter 和 View 需要接口交互,所以会导致接口类过多。下面用表格总结一下两者关系:
| 类别 | 优点 | 缺点 | 特点 |
|---|---|---|---|
| MVC | 容易理解、快速上手、使用简单 | Activity 逻辑与 UI 过重将导致迭代维护困难 | 简单易学 |
| MVP | View 与 Model 完全隔离、Presenter 可重用、便于测试 | View 层过重,需要在 Base 抽象通用 View,接口类过多,开发耗时 | 完全解耦 |
示例说明——登录界面需求
model 层代码编写
根据业务书写 Model 层的数据(用户名和密码)以及业务逻辑(登录的具体步骤),与 MVC 中的相同,这里就不贴代码了,可以参考上篇文章的 Model 层的书写。
View 层代码编写
定义接口,因为 Presenter 需要接口与 View 交互的接口方法。接口中方法的定义,编写的思路可以按照下面的方法:
- 该操作需要什么?
- 该操作的结果,对应的反馈?(success, failed)
- 该操作过程中对应的友好的交互?(showLoading, hideLoading)
//Presenter 和 View 的交互,通过该接口实现
public interface LoginView {
void showLoading();
void hideLoading();
void success();
void failed();
}
Presenter 层代码编写
作为 View 和 Model 之间交互的桥梁,包含的方法主要还是看该功能有什么操作,同时完成两者的交互,就需要二者的实现类,从 View 中获取需要的参数,然后交给 Model 去执行业务方法。执行过程中需要的反馈和结果,再让 View 进行对应的显示。
public class LoginPresenter {
private LoginView mLoginView;
private LoginModel model;
private Context mContext;
public LoginPresenter(Context context, LoginView mLoginView) {
this.mLoginView = mLoginView;
model = new LoginModelImpl();
this.mContext = context;
}
public void login(String account,String password) {
if (TextUtils.isEmpty(account)||TextUtils.isEmpty(password)){
Toast.makeText(mContext,"请输入账号和密码!",Toast.LENGTH_SHORT).show();
}else {
mLoginView.showLoading();
model.login(account, password, new LoginListener() {
@Override
public void success() {
mLoginView.success();
mLoginView.hideLoading();
}
@Override
public void error() {
mLoginView.failed();
mLoginView.hideLoading();
}
});
}
}
}
在 Activity 中的代码如下:
public class MainActivity extends AppCompatActivity implements View.OnClickListener,LoginView{
private EditText editAccount,editPassword;
private Button loginBtn,clearBtn;
private ProgressDialog dialog;
private LoginPresenter loginPresenter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initViews();
}
private void initViews() {
editAccount = (EditText) findViewById(R.id.edit_account);
editPassword = (EditText) findViewById(R.id.edit_pwd);
loginBtn = (Button) findViewById(R.id.btn_login);
clearBtn = (Button) findViewById(R.id.btn_reset);
dialog = new ProgressDialog(this);
dialog.setMessage("正在登陆,请稍后...");
dialog.setCanceledOnTouchOutside(false);
loginPresenter = new LoginPresenter(this,this);
initListener();
}
private void initListener() {
loginBtn.setOnClickListener(this);
clearBtn.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_login:
loginPresenter.login(editAccount.getText().toString(),editPassword.getText().toString());
break;
default:
break;
}
}
@Override
public void showLoading() {
dialog.show();
}
@Override
public void hideLoading() {
dialog.dismiss();
}
@Override
public void success() {
Toast.makeText(this,"登陆成功!",Toast.LENGTH_SHORT).show();
}
@Override
public void failed() {
Toast.makeText(this,"登陆失败!",Toast.LENGTH_SHORT).show();
}
}
这样的架构在项目代码中显得逻辑更加清晰,样式更加简洁。这是 MVP 架构带来的直观感受。
在下一篇文章 Android架构模式的简单封装,我们会做一些 MVP 的简单封装来优化 MVP 的使用。

浙公网安备 33010602011771号