MVC MVP MVVM
- MVC
MVC模式的意思是,分成三个部分.
- view: 视图,用户界面(activity的layout)
- controller: 控制器,业务逻辑
- model : 模型, 数据保存
各部分直接保留着相互通信: 如下:
- view 传送指令到 controller
- controller 完成业务逻辑后,要求model改变状态
- model 将新的数据发送到view,用户得到反馈。
通信方式为单向。
- 互动模式
接受用户模式时,MVC可以分为两种方式,一种是通过view接受指令,传递给controller。
另外一种是通过controller接受指令
MVP
MVP 模式将Controller 改名为 Presenter, 同时改变了通信方向。
- 各部分间的通信都是双向的.
- view 与model 不发生联系,都通过Presenter传递
- view 非常薄,不部署任何业务逻辑,称为“被动视图”(passive view)
即没有任何主动性,而presenter非常厚,所有逻辑部署在那里。
MVP IN Android
在android里面使代码更加清晰,不过增加了很多类。
- View : 将activity 视为View 层, 负责View 的绘制以及与用户的交互
- Model : 依然是业务逻辑和实体模型
- Presenter : 负责完成 View 与 Model 间的交互
文件夹 : MVP, 里面有bean, biz, prestener, view 等文件夹
Model
实体类User , 里面至少有一个业务方法,login().
public class User {
private String userName;
private String password;
//get set 方法
...
}
biz下创建一个接口 : IUserBiz
public interface IUserBiz {
public void login(String username, String passward, OnLoginListener loginListener);
}
里面利用到了,另外一个接口OnLoginListener.
public interface OnLoginListener {
void loginSuccess(User user);
void loginFailed();
}
在biz 下 UserBiz
public class UserBiz implements IUserBiz {
@Override
public void login(final String username, final String password,
final OnListener loginListener) {
//
new Thread() {
@Overdide
public void run() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//模拟登录成功
if (username.equals("...") && passward.equals("...")) {
User user = new User();
user.setUsername(username);
user.setPassword(password);
loginListener.loginSuccess(user);
} else {
loginListener.loginFailed();
}
}
}.start();
}
}
在业务类,抽取了一个接口,一个实现类很常见,login(), 一般肯定是连接服务器的,是个耗时操作,
开了一个子线程,模拟了耗时,由于是耗时操作,所以通过一个回调接口来通知登录的状态。
waiting
这里大部分和以前的写法没区别。
View
Presenter 与View 交互式通过接口。定义一个ILoginView, 效果图:
有两个按钮,一个是login,一个是clear;
login说明要有用户名和密码,对应两个方法;
再者login是个耗时的操作,需要给用户一个友好的提示,一般加一个ProgressBar,所以有两个:
void showLoading();
void hideLoading();
login
还存在着登录成功和失败的处理,主要看成功去跳转activity,而失败去给个提醒:
void toMainActivity(User user);
void showFailedError();
clear 需要
void clearUserName();
void clearPassword();
综上: IUserLoginView
接口完整为 :
public interface IUserLoginView {
String getUserName();
String getPassword();
void clearUserName();
void clearPassword();
void showLoading();
void hideLoading();
void toMainActivity(User user);
void showFailedError();
}
需要实现接口,方便很多。
对于View接口,去观察功能上的操作,然后考虑 :
- 该操作需要什么 (getUserName, getPassword)
- 该操作的结果,对应的反馈? (toMainActivity, showFailedError)
- 该操作过程中对应的友好的交互 ? (showLoading, hideLoading)
view 的实现类 :
其实就是activity, MVP中的view其实就是activity.
public class UserLoginActivity extends ActionBarActivity implements IUserLoginView {
private UserLoginPresenter mUserLoginPresenter = new UserLoginPresenter(this);
@Bind(R.id.username) protected EditText mEditUsername;
@Bind(R.id.password) protected EditText mEditPassword;
@Bind(R.id.login) protected Button mButtonLogin;
@Bind(R.id.clear) protected Button mButtonClear;
@Bind(R.id.progress_loading) protected ProgressBar mPbLoading;
@OnClick(R.id.login) void login() {
mUserLoginPresenter.login();
}
@OnClick(R.id.clear) void clear() {
mUserLoginPresenter.clear();
}
@Override
protected void onCreat(Bundle savedInstanceState) {
super.onCreat(savedInstanceState);
setContentView(R.layout.activity_user_login);
ButterKnife.bind(this);
}
@Override
public String getUserName() {
return mEditUsername.getText().toString();
}
@Override
public String getPassword() {
return mEditPassword.getText().toString();
}
@Override
public void clearUserName() {
mEditUsername.setText("");
}
@Override
public void clearPassword() {
mEditPassword.setText("");
}
@Override
public void showLoading()
{
mPbLoading.setVisibility(View.VISIBLE);
}
@Override
public void hideLoading()
{
mPbLoading.setVisibility(View.GONE);
}
@Override
public void toMainActivity(User user)
{
Toast.makeText(this, user.getUsername() +
" login success , to MainActivity", Toast.LENGTH_SHORT).show();
}
@Override
public void showFailedError()
{
Toast.makeText(this,
"login failed", Toast.LENGTH_SHORT).show();
}
}
上面是view层.
在去看Presenter层, 里面的UserLoginPresenter
Presenter
presenter 作为mode 与view 之间交互的桥梁,
public class UserLoginPresenter {
private IUserBiz userBiz;
private IUserLoginView userLoginView;
private Handler mHandler = new Handler();
public UserLoginPresenter(IUserLoginView userLoginView) {
this.userLoginView = userLoginView;
this.userBiz = new UserBiz();
}
public void login() {
userLoginView.showLoading();
userBiz.login(userLoginView.getUserName(), userLoginView.getPassword(),
new OnLoginListener(){
@Override
public void loginSuccess(final User user)
{
//需要在UI线程执行
mHandler.post(new Runnable()
{
@Override
public void run() {
userLoginView.toMainActivity(user);
userLoginView.hideLoading();
}
});
}
@Override
public void loginFailed(){
//需要在UI线程执行
mHandler.post(new Runnable(){
@Override
public void run(){
userLoginView.showFailedError();
userLoginView.hideLoading();
}
});
}
});
}
public void clear() {
userLoginView.clearUserName();
userLoginView.clearPassword();
}
}
注意上面的代码里,presenter 完成view 和model的交互,需要二者的实现类,
是从view 中获取需要的参数,交给Model去执行业务方法,执行的过程需要的反馈,
以及结果,再让view进行对应的显示.
MVVM
MVVM 模式将presenter 改名为ViewModel, 基本上与MVP模式完全一致
唯一的区别是它采用了双向绑定(data-binding) : view 的变动,自动反映在
ViewModel, 反之亦然。
从 :
转变为 :
