整理自mvp
MVP 模式(Model-View-Presenter)可以说是 MVC 模式(Model-View-Controller)在 Android 开发上的一种变种、进化模式。
在 MVC 模式中,Activity 应该是属于 View 这一层。而实质上,它既承担了 View,同时也包含一些 Controller 的东西在里面。这对于开发与维护来说不太友好,耦合度大高了。把 Activity 的 View 和 Controller 抽离出来就变成了 View 和 Presenter,这就是 MVP 模式。
MVC 模式的结构分为三部分,实体层的 Model,视图层的 View,以及控制层的 Controller。
- 其中 View 层其实就是程序的 UI 界面,用于向用户展示数据以及接收用户的输入
- 而 Model 层就是 JavaBean 实体类,用于保存实例数据
- Controller 控制器用于更新 UI 界面和数据实例
按照 MVC 的分层,Activity 和 Fragment(后面只说 Activity)应该属于 View 层,用于展示 UI 界面,以及接收用户的输入,此外还要承担一些生命周期的工作。Activity 是在 Android 开发中充当非常重要的角色,特别是 TA 的生命周期的功能,所以开发的时候我们经常把一些业务逻辑直接写在 Activity 里面,这非常直观方便,代价就是 Activity 会越来越臃肿,所以看起来有必要在 Activity 中,把 View 和 Controller 抽离开来,而这就是 MVP 模式的工作了。
核心思想:
MVP 把 Activity 中的 UI 逻辑抽象成 View 接口,把业务逻辑抽象成 Presenter 接口,Model 类还是原来的 Model。
这就是 MVP 模式,现在这样的话,Activity 的工作的简单了,只用来响应生命周期,其他工作都丢到 Presenter 中去完成。
上面一张简单的 MVP 模式的 UML 图,从图中可以看出,使用 MVP,至少需要经历以下步骤:
- 创建 IPresenter 接口,把所有业务逻辑的接口都放在这里,并创建它的实现 PresenterCompl(在这里可以方便地查看业务功能,由于接口可以有多种实现所以也方便写单元测试)
- 创建 IView 接口,把所有视图逻辑的接口都放在这里,其实现类是当前的 Activity/Fragment
- 由 UML 图可以看出,Activity 里包含了一个 IPresenter,而 PresenterCompl 里又包含了一个 IView 并且依赖了 Model。Activity 里只保留对 IPresenter 的调用,其它工作全部留到 PresenterCompl 中实现
- Model 并不是必须有的,但是一定会有 View 和 Presenter
MVP 的主要特点就是把 Activity 里的许多逻辑都抽离到 View 和 Presenter 接口中去,并由具体的实现类来完成。这种写法多了许多 IView 和 IPresenter 的接口
一个简单的登录界面:
/**
* @author HaoTianYi [email protected]
* @version v1.0
* @des 作为view的实现
* @time 2016-11-21 17:00
*/
public class MainActivity extends AppCompatActivity implements IView,View.OnClickListener{
IPresenter mPresenter;
private EditText editUser;
private EditText editPass;
private Button btnLogin;
private Button btnClear;
private ProgressBar progressBar;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//find view
editUser = (EditText) this.findViewById(R.id.et_login_username);
editPass = (EditText) this.findViewById(R.id.et_login_password);
btnLogin = (Button) this.findViewById(R.id.btn_login_login);
btnClear = (Button) this.findViewById(R.id.btn_login_clear);
progressBar = (ProgressBar) this.findViewById(R.id.progress_login);
//set listener
btnLogin.setOnClickListener(this);
btnClear.setOnClickListener(this);
//init
mPresenter = new PresenterCompl(this);
mPresenter.setProgressBarVisiblity(false);
}
@Override
public void onClesrText() {
editUser.setText("");
editPass.setText("");
}
@Override
public void onSuccessAndRefuslView(boolean result) {
Toast.makeText(MainActivity.this,result?"成功":"失败",Toast.LENGTH_SHORT).show();
}
@Override
public void onShowDIalog(boolean result) {
progressBar.setVisibility(result?View.VISIBLE:View.GONE);
}
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.btn_login_clear:
mPresenter.setClearText();
break;
case R.id.btn_login_login:
mPresenter.setProgressBarVisiblity(true);
btnLogin.setEnabled(false);
btnClear.setEnabled(false);
mPresenter.doLogin(editUser.getText().toString(), editPass.getText().toString());
break;
}
}
IPresenter的写法:
/**
* @author HaoTianYi [email protected]
* @version v1.0
* @des 三个方法,控制视图的不同显示
* @time 2016-11-21 17:08
*/
public interface IPresenter {
/**
* 清空输入框的文字
*/
void setClearText();
/**
* 登录操作
* @param name
* @param passwd
*/
void doLogin(String name, String passwd);
/**
* 设置progressBar是否显示
* @param result
*/
void setProgressBarVisiblity(boolean result);
}
IModel的写法:
/**
* @author HaoTianYi [email protected]
* @version v1.0
* @des 获得用户的用户名和密码并且判断是否符合规则
* @time 2016-11-21 17:03
*/
public interface IModel {
String getName();
String getPssword();
boolean isSuccess(String name,String password);
}
PresenterCompl的写法:
public class PresenterCompl implements IPresenter {
IView mIView;
IModel mIModel;
Handler mHandler;
public PresenterCompl(IView iView) {
mIView = iView;
mHandler = new Handler(Looper.getMainLooper());
}
@Override
public void setClearText() {
mIView.onClesrText();
}
@Override
public void doLogin(final String name, final String passwd) {
mIModel = new ModelCompl(name, passwd);
final boolean isSuccess = mIModel.isSuccess(name, passwd);
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
mIView.onSuccessAndRefuslView(isSuccess);
mIView.onShowDIalog(!isSuccess);
}
}, 3000);
}
@Override
public void setProgressBarVisiblity(boolean result) {
mIView.onShowDIalog(result);
}
具体代码:GitHub