1、概述
MVP架构可以使代码更清晰与MVC的区别是,Presenter的出现,将Actvity视为View层,Presenter负责完成View层与Model层的交互。
(1)View 对应于Activity,负责View的绘制以及与用户交互
(2)Model 是实体模型
(3)Presenter 负责完成View于Model间的交互及业务逻辑
而MVC架构中
(1)View:对应于布局文件
(2)Model:业务逻辑和实体模型
(3)Controllor:对应于Activity
MVC
到MVP
的一个转变,减少了Activity的职责,简化了Activity中的代码,将复杂的逻辑代码提取到了Presenter中进行处理。与之对应的好处就是,耦合度更低,更方便的进行测试。
MVC中是允许Model和View进行交互的,而MVP中很明显,Model与View之间的交互由Presenter完成。还有一点就是Presenter与View之间的交互是通过接口的。
2. 步骤:
(1)创建 IPresenter 接口,把所有业务逻辑的接口都放在这里,并创建它的实现 PresenterCompl(在这里可以方便地查看业务功能,由于接口可以有多种实现所以也方便写单元测试)。
(2)创建 IView 接口,把所有视图逻辑的接口都放在这里,其实现类是当前的 Activity/Fragment。
(3)Activity 里包含了一个 IPresenter,而 PresenterCompl 里又包含了一个 IView 并且依赖了 Model。Activity 里只保留对 IPresenter 的调用,其它工作全部留到 PresenterCompl中实现。
(4)Model 并不是必须有的,但是一定会有 View 和 Presenter。
通过上面的介绍,MVP 的主要特点就是把 Activity 里的许多逻辑都抽离到 View 和 Presenter 接口中去,并由具体的实现类来完成。这种写法多了许多 IView 和 IPresenter 的接口。
3.简单的登录案列
(1)model层
业务逻辑分析;登录有用户名和密码,登录成功和失败的业务逻辑所以先创建一个user类,其次一个包含登录的接口,再者登录成功失败的接口,其中登录的方法参数包含用户名和密码、监听接口。
如下:
①public class User
{
private String username ;
private String password ;
public String getUsername()
{
return username;
}
public void setUsername(String username)
{
this.username = username;
}
public String getPassword()
{
return password;
}
public voidsetPassword(String password)
{
this.password = password;
}
}
②public
interface IUserBiz
{
publicvoidlogin
(String username, String password, OnLoginListener loginListener);
}
③public
interface OnLoginListener
{
void
loginSuccess(User user);
void
loginFailed();
}
④public
class UserBiz implements IUserBiz
{
@Override
publicvoidlogin
(
finalString username,
finalString password,
finalOnLoginListener loginListener)
{
//模拟子线程耗时操作
new
Thread()
{
@Override
publicvoidrun
()
{
try
{
Thread.sleep(
2000);
}
catch(InterruptedException e)
{
e.printStackTrace();
}
//模拟登录成功
if
(
"zhy".equals(username) &&
"123".equals(password))
{
User user =
newUser();
user.setUsername(username);
user.setPassword(password);
loginListener.loginSuccess(user);
}
else
{
loginListener.loginFailed();
}
}
}.start();
}
}
(2)view层也就是activity层
从界面
可以看到如果有两个按钮,一个是login,一个是clear;
login说明了要有用户名、密码,那么对应两个方法:
String getUserName();
String getPassword();
再者login是个耗时操作,我们需要给用户一个友好的提示,一般就是操作ProgressBar,所以再两个:
void
showLoading();
void
hideLoading();
login当然存在登录成功与失败的处理,我们主要看成功我们是跳转Activity,而失败可能是去给个提醒:
void
toMainActivity(User user);
void
showFailedError();
还剩个clear:
void
clearUserName();
void
clearPassword();
所以接口可以这样定义:public
interface IUserLoginView
{
String getUserName();
String getPassword();
void
clearUserName();
void
clearPassword();
void
showLoading();
void
hideLoading();
void
toMainActivity(User user);
void
showFailedError();
}
View层对应的activity层所以activity如下;
publicclassUserLoginActivityextendsActionBarActivityimplementsIUserLoginView
{
private
EditText mEtUsername, mEtPassword;
private
Button mBtnLogin, mBtnClear;
private
ProgressBar mPbLoading;
private
UserLoginPresenter mUserLoginPresenter =
newUserLoginPresenter(
this);
@Override
protectedvoidonCreate
(Bundle savedInstanceState)
{
super
.onCreate(savedInstanceState);
setContentView(R.layout.activity_user_login);
initViews();
}
privatevoidinitViews
()
{
mEtUsername = (EditText) findViewById(R.id.id_et_username);
mEtPassword = (EditText) findViewById(R.id.id_et_password);
mBtnClear = (Button) findViewById(R.id.id_btn_clear);
mBtnLogin = (Button) findViewById(R.id.id_btn_login);
mPbLoading = (ProgressBar) findViewById(R.id.id_pb_loading);
mBtnLogin.setOnClickListener(
newView.OnClickListener()
{
@Override
publicvoidonClick
(View v)
{
mUserLoginPresenter.login();
}
});
mBtnClear.setOnClickListener(
newView.OnClickListener()
{
@Override
publicvoidonClick
(View v)
{
mUserLoginPresenter.clear();
}
});
}
@Override
public
String
getUserName()
{
return
mEtUsername.getText().toString();
}
@Override
public
String
getPassword()
{
return
mEtPassword.getText().toString();
}
@Override
publicvoidclearUserName
()
{
mEtUsername.setText(
"");
}
@Override
publicvoidclearPassword
()
{
mEtPassword.setText(
"");
}
@Override
publicvoidshowLoading
()
{
mPbLoading.setVisibility(View.VISIBLE);
}
@Override
publicvoidhideLoading
()
{
mPbLoading.setVisibility(View.GONE);
}
@Override
publicvoidtoMainActivity
(User user)
{
Toast.makeText(
this, user.getUsername() +
" login success , to MainActivity"
, Toast.LENGTH_SHORT).show();
}
@Override
publicvoidshowFailedError
()
{
Toast.makeText(
this,
"login failed"
, Toast.LENGTH_SHORT).show();
}
}
(3) Presenter是连接view和model层所以presenter调用view和model层的方法
publicclassUserLoginPresenter
{
private
IUserBiz userBiz;
private
IUserLoginView userLoginView;
private
Handler mHandler =
newHandler();
publicUserLoginPresenter
(IUserLoginView userLoginView)
{
this
.userLoginView = userLoginView;
this
.userBiz =
newUserBiz();
}
publicvoidlogin
()
{
userLoginView.showLoading();
userBiz.login(userLoginView.getUserName(), userLoginView.getPassword(),
newOnLoginListener()
{
@Override
publicvoidloginSuccess
(
finalUser user)
{
//需要在UI线程执行
mHandler.post(
newRunnable()
{
@Override
publicvoidrun
()
{
userLoginView.toMainActivity(user);
userLoginView.hideLoading();
}
});
}
@Override
publicvoidloginFailed
()
{
//需要在UI线程执行
mHandler.post(
newRunnable()
{
@Override
publicvoidrun
()
{
userLoginView.showFailedError();
userLoginView.hideLoading();
}
});
}
});
}
publicvoidclear
()
{
userLoginView.clearUserName();
userLoginView.clearPassword();
}
}