以App登录功能为例说明MVP实现,登录界面如下所示:
功能如下:点击登录进行网络请求,同时显示”登录中“提示框,登录成功提示框消失并进入mainActivity界面,登录失败提示框消失并给用户弹出toast提示出错原因。点击清除用户和密码,清除editText中内容。
model接口以及实现类:
/**
* Model接口执行具体的业务逻辑。
* 如何确定model中应该做什么(有哪些方法?)以及做这些工作需要view提供哪些数据(方法中有哪些参数?)
* 看这个界面需要做哪些工作,这就是你这个界面的业务逻辑了。显然登录界面至少需要登录操作,登录操作需要view提供用户名、密码
*/
public interface ILoginModel {
void login(String userName, String password, LoginListener loginListener);
}
public class LoginModel implements ILoginModel {
@Override
public void login(final String userName, final String password, final LoginListener loginListener) {
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (userName.equals("张三")&&password.equals("123")) {
loginListener.loginSuccess(new User(userName,password));
}else {
loginListener.loginFailed(1000);
}
}
}).start();
}
}
view接口以及实现类:
/**
* view接口的作用是:获取用户输入的数据+model执行业务逻辑过程中以及业务执行结束后,界面的变化
* 如何考虑view中应该有哪些操作?三方面:
* 1、view应该获取哪些数据给model执行业务逻辑
* 2、model执行业务逻辑过程中,view应该与用户有哪些交互?界面如何变化?(弹出对话框、进度条)
* 3、model执行业务逻辑结束后,view应该与用户有哪些交互?界面如何变化?(跳转到别的界面、弹出toast)
*/
public interface ILoginView {
//view应该获取的数据
String getUserName();
String getPassword();
//model执行登录逻辑时,显示"正在加载"弹窗
void showLoading();
//model执行业务逻辑结束后,弹窗消失,根据登录结果选择跳转页面还是报错提示
void dismissLoading();
void toMainActivity();
void showErrorToast();
//清除editText中的内容
void clearUserName();
void clearPassword();
}
public class LoginActivity extends Activity implements ILoginView , View.OnClickListener{
private static final int LOGIN_BTN_ID = 1;
private static final int CLEAR_BTN_ID = 2;
private EditText mUserNameEt;
private EditText mPasswordEt;
private Button mLoginBtn;
private Button mClearBtn;
private ILoginPresenter loginPresenter = new LoginPresenter(this);
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
initView();
}
private void initView() {
//省略了findViewById
mLoginBtn.setOnClickListener(this);
mClearBtn.setOnClickListener(this);
}
@Override
public String getUserName() {
return mUserNameEt.getText().toString().trim();
}
@Override
public String getPassword() {
return mPasswordEt.getText().toString().trim();
}
@Override
public void showLoading() {
//登录中。。
}
@Override
public void dismissLoading() {
//弹窗消失
}
@Override
public void toMainActivity() {
//页面跳转
}
@Override
public void showErrorToast() {
Toast.makeText(this,"登录失败",Toast.LENGTH_SHORT).show();
}
@Override
public void clearUserName() {
mUserNameEt.setText("");
}
@Override
public void clearPassword() {
mPasswordEt.setText("");
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case LOGIN_BTN_ID:
loginPresenter.login();
break;
case CLEAR_BTN_ID:
loginPresenter.clearUserName();
loginPresenter.clearUserName();
break;
}
}
presenter接口以及实现类:
/**
* Presenter是model和view的桥梁,presenter中持有view和model的引用,在presenter中调用view和model的接口完成业务流程:
* 在presenter中调用view的api获取数据给model,调用model的api执行业务逻辑,调用view的api显示model执行过程中和执行完成后的界面变化。
* 那如何确定presenter有哪些操作?也是看界面中有哪些业务逻辑,登录界面有登录逻辑以及清除用户名和密码框中内容的逻辑
*/
public interface ILoginPresenter {
void login();
void clearUserName();
void clearPassword();
}
public class LoginPresenter implements ILoginPresenter {
private ILoginModel loginModel;
private ILoginView loginView;
public LoginPresenter(ILoginView loginView) {
this.loginView = loginView;
loginModel = new LoginModel();
}
@Override
public void login() {
//显示登录提示框
loginView.showLoading();
//登录
loginModel.login(loginView.getUserName(), loginView.getPassword()
, new LoginListener() {
@Override
public void loginSuccess(User user) {
//登录成功后提示框消失并跳转界面
loginView.toMainActivity();
loginView.dismissLoading();
}
@Override
public void loginFailed(int errorCode) {
//登录失败后提示框消失并给用户弹出登录失败toast
loginView.showErrorToast();
loginView.dismissLoading();
}
});
}
@Override
public void clearUserName() {
loginView.clearUserName();
}
@Override
public void clearPassword() {
loginView.clearPassword();
}
user对象以及登录结果回调接口:
/**
* 实体对象
*/
public class User {
private String userName;
private String password;
public User(String userName, String password) {
this.userName = userName;
this.password = password;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
}
public interface LoginListener {
void loginSuccess(User user);
void loginFailed(int errorCode);
}
总结如下:
view负责获取界面上的数据给model执行业务,model执行业务过程中的反馈、执行结果需要view进行界面显示
model负责执行业务逻辑,需要的数据由view提供
Presenter是model和view的桥梁,presenter中持有view和model的引用,在presenter中调用view的接口显示界面变化、调用model的接口执行业务逻辑,从而完成整个业务流程。
MVP真正实现了MVC没有实现的分层,分层逻辑清晰,代码耦合度低