MVP模式是MCV模式在Android平台上的变体。
从MVC模式的角度来看,在Android中Activity既是 “V” 又是 “C” ,业务代码与显示代码的耦合度非常高。把Activity中的View和Controller抽离出来变成View和Presenter,这就是MVP模式。
一、MVC模式和MVP模式的对比
MVC与MVP的不同在于“M”能否直接和“V”交互。如下图:
MVC:
MVP:
二、MVP模式的作用
1.分离了视图逻辑和业务逻辑,降低了耦合
2.Activity 只处理生命周期的任务,代码变得更加简洁
3.视图逻辑和业务逻辑分别抽象到了 View 和 Presenter 的接口中去,提高代码的可阅读性
4.Presenter 被抽象成接口,可以有多种具体的实现,所以方便进行单元测试
5.把业务逻辑抽到 Presenter 中去,避免后台线程引用着 Activity 导致 Activity 的资源无法被系统回收从而引起内存泄露和 OOM
三、示例
代码树结构
MainActivity
public class MainActivity extends AppCompatActivity implements ILoginView, View.OnClickListener {
ILoginPresenter loginPresenter = new LoginPresenterImpl(this);
private EditText mUsername;
private EditText mPassword;
private Button mButton;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mUsername = (EditText) findViewById(R.id.username);
mPassword = (EditText) findViewById(R.id.password);
mButton = (Button) findViewById(R.id.btn);
mButton.setOnClickListener(this);
}
@Override
public void onClick(View view) {
if (view.getId() == R.id.btn) {
loginPresenter.login(mUsername.getText().toString(), mPassword.getText().toString());
}
}
@Override
public void onShowMessage(String msg) {
Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
}
}
ILoginView
public interface ILoginView {
void onShowMessage(String msg);
}
ILoginPresenter
public interface ILoginPresenter {
void login(String username, String password);
}
LoginPresenterImpl
public class LoginPresenterImpl implements ILoginPresenter {
private ILoginView mLoginView;
private User mUser;
public LoginPresenterImpl(ILoginView loginView) {
mLoginView = loginView;
mUser = new User();
}
@Override
public void login(String username, String password) {
boolean isValid = mUser.isValid(username, password);
if (isValid) {
mLoginView.onShowMessage("login success");
} else {
mLoginView.onShowMessage("login failed");
}
}
}
User
public class User {
public boolean isValid(String username, String password) {
if (username != null && !username.isEmpty() && password != null && !password.isEmpty()) {
return true;
}
return false;
}
}
运行结果