在开发Android应用时,一个偶然的机会看到有种MVP模式(Mode-View-Presenter),然后好奇的研究了下这个模式并尝试在现在项目中进行推广。下面就把自己目前学习到知识总结出来。
一、MVP简介
我理解的MVP是由MVC优化衍生出来的一种模式,MVP将MVC中的Controller层进行了优化而生成了Presenter。Presenter单词翻译为“提出者;任命者;主持人”,Presenter层和MVC的Controller一样,负责核心逻辑,但不一样的是Presenter通过接口协议进行数据传递,并阻断了View和Model的直接联系,从而使View和Model更加专注于自身业务逻辑
二、MVP结构
View
View通常来说就是有Activity、Fragment实现的,View会包含一个或多个Presenter的引用来满足视图的业务逻辑。View和Presenter的交互是双向的,即View层可以调用Presenter的逻辑方法,Presenter也可以控制View的显示。
Presenter
Presenter作为Model和View的桥梁,负责从Model拿到数据进行处理并返回给View。但Presenter和其他两层的沟通是通过接口协议进行的,所以每个Presenter中通常会包涵一个或多个接口协议。
Model
和MVC一样,作为数据仓库只负责对APP数据进行处理。
三、MVP实例(MVPLogin)
在这里我以登录为例来应用MVP模式,来加深对于MVP模式的认知。
1、先来看看项目的结构图:
1、View的示例:LoginActivity这个就不说了,ILoginView这个也是一个接口,从LoginActivity中抽离出来的
方法,LoginActivity实现了ILoginView这个接口。
ILoginView.java:
package com.tz.mvplogin.login.view;
public interface ILoginView {
/**
* 获取用户名
*
* @return
*/
public String getUserName();
/**
* 获取密码
*
* @return
*/
public String getPassWord();
/**
* 显示dialog
*/
public void showDialog();
/**
* 隐藏dialog
*/
public void hideDialog();
/**
* 显示信息
*/
public void showMsg(String msg);
/**
* 跳入MainActivity
*/
public void pushMainActivity();
} MainActivity.java:
package com.tz.mvplogin.login.view;
import com.tz.mvplogin.CustomToast;
import com.tz.mvplogin.MainActivity;
import com.tz.mvplogin.R;
import com.tz.mvplogin.login.persenter.LoginPersenter;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.widget.Button;
import android.widget.EditText;
public class LoginActivity extends Activity implements OnClickListener,
ILoginView {
private EditText mEditTextUserName, mEditTextPassword;
private Button mButtonLogin;
private ProgressDialog mProgressDialog;
private LoginPersenter mPersenter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_login);
initWeight();
}
private void initWeight() {
mEditTextUserName = (EditText) findViewById(R.id.et_username);
mEditTextPassword = (EditText) findViewById(R.id.et_password);
mButtonLogin = (Button) findViewById(R.id.bt_login);
mButtonLogin.setOnClickListener(this);
mProgressDialog = new ProgressDialog(LoginActivity.this);
mProgressDialog.setTitle("提示");
mProgressDialog.setMessage("正在登录...");
mPersenter = new LoginPersenter(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.bt_login:
mPersenter.login(getUserName(), getPassWord());
break;
default:
break;
}
}
@Override
public String getUserName() {
return mEditTextUserName.getText().toString();
}
@Override
public String getPassWord() {
return mEditTextPassword.getText().toString();
}
@Override
public void showDialog() {
mProgressDialog.show();
}
@Override
public void hideDialog() {
mProgressDialog.dismiss();
}
@Override
public void showMsg(String msg) {
CustomToast.showToast(this, msg, 2000);
}
@Override
public void pushMainActivity() {
startActivity(new Intent(this, MainActivity.class));
finish();
}
} 大家有木有发现Activity的代码好少
,也清晰了好多,没有一点关于逻辑的代码。。。
嘎嘎。。那逻辑代码去哪了?别介。。下面就出来了。
2、model的示例:IloginModel是一个接口,里面的方法是从LoginModel中抽象出来的。而LoginModel实现
了ILoginModel这个接口。
IloginModel.java:
package com.tz.mvplogin.login.model;
import com.tz.mvplogin.login.ICallBack;
public interface ILoginModel {
public static final int NETWORK_ERROR = 1;
public static final int LOGIN_SUCCESS = 2;
public static final int LOGIN_FALUIRE = 3;
public static final int LOGIN_ING = 4;
public static final int CHECK_FALUIRE = 5;
public void login(String username, String password, ICallBack callBack);
} LoginModel.java:
package com.tz.mvplogin.login.model;
import com.avos.avoscloud.AVException;
import com.avos.avoscloud.AVUser;
import com.avos.avoscloud.LogInCallback;
import com.tz.mvplogin.application.App;
import com.tz.mvplogin.login.ICallBack;
public class LoginModel implements ILoginModel {
private int status = ILoginModel.NETWORK_ERROR;
private String msg = "";
@Override
public void login(String username, String password, final ICallBack callBack) {
if (validate(username, password)) {
setStatus(ILoginModel.LOGIN_ING);
callBack.status(this);
AVUser.logInInBackground(username, password,
new LogInCallback() {
@Override
public void done(AVUser user, AVException e) {
if (user != null) {
// 登录成功
setStatus(ILoginModel.LOGIN_SUCCESS);
setMsg("登陆成功");
App.setUser(user);
callBack.status(LoginModel.this);
} else {
// 登录失败
e.printStackTrace();
setStatus(ILoginModel.LOGIN_FALUIRE);
setMsg("登陆失败");
callBack.status(LoginModel.this);
}
}
});
} else {
callBack.status(this);
}
}
/**
*
* @description 验证输入信息
* @author houhou
* @version 1.0
* @createDate 2015年8月3日下午10:54:28
* @return
*/
private boolean validate(String username, String password) {
if (username.length() == 0) {
status = ILoginModel.CHECK_FALUIRE;
msg = "用户名不能为空";
return false;
}
if (password.length() == 0) {
status = ILoginModel.CHECK_FALUIRE;
msg = "密码不能为空";
return false;
}
return true;
}
public int getStatus() {
return status;
}
public void setStatus(int status) {
this.status = status;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
} 发现了吧。。逻辑代码从Activity中完全抽离出来了
。呵呵,得瑟,抽离是抽离出来了,着你怎么和界面进行数据交互呢
?这个就要靠咱们的主持人Presenter了
,接下来有请主持人闪亮登场
。。。。
3、Presenter示例:这个分别类持有IloginModel和ILoginView这两个对象,一个是数据逻辑,一个是界面交互。
哈哈,看到这明白了吧,我左手(ILoginModel)右手(ILoginView)一起慢动作
,逻辑和界面就交互了。
Presenter.java:
package com.tz.mvplogin.login.persenter;
import com.tz.mvplogin.login.ICallBack;
import com.tz.mvplogin.login.model.ILoginModel;
import com.tz.mvplogin.login.model.LoginModel;
import com.tz.mvplogin.login.view.ILoginView;
public class LoginPresenter {
private ILoginView mLoginView;// 视图层
private ILoginModel mLoginModel;// 逻辑层
public LoginPresenter(ILoginView view) {
mLoginView = view;
mLoginModel = new LoginModel();
}
public void login(String username, String password) {
mLoginModel.login(username, password, new ICallBack() {
@Override
public void status(LoginModel model) {
switch (model.getStatus()) {
case ILoginModel.LOGIN_ING:
mLoginView.showDialog();
break;
case ILoginModel.CHECK_FALUIRE:
mLoginView.showMsg(model.getMsg());
break;
case ILoginModel.LOGIN_FALUIRE:
mLoginView.hideDialog();
mLoginView.showMsg(model.getMsg());
break;
case ILoginModel.LOGIN_SUCCESS:
mLoginView.hideDialog();
mLoginView.pushMainActivity();
break;
}
}
});
}
}4、到这里,MVP模式算是说完了,还有一个ICallBack是一个登录完成后回调的一个接口类:
ICallBack.java:
package com.tz.mvplogin.login;
import com.tz.mvplogin.login.model.LoginModel;
public interface ICallBack {
public void status(LoginModel model);
}哦,差点忘了说了,登录用户名和密码都是:mvplogin(这个是用的LeanCloud,不知道的可以问问度娘)。
下面是运行截图:
这里我放上这个Demo的下载地址