*/
public interface OnLoginListener {
void loginSuccess(User user);
void loginFailed();
}
/**
- 具体Model的实现
*/
public class UserBiz implements IUserBiz {
@Override
public void login(final String username, final String password, final OnLoginListener loginListener) {
//模拟子线程耗时操作
new Thread() {
@Override
public void run() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//模拟登录成功
if (“zhy”.equals(username) && “123”.equals(password)) {
User user = new User();
user.setUsername(username);
user.setPassword(password);
loginListener.loginSuccess(user);
} else {
loginListener.loginFai
led();
}
}
}.start();
}
}
//View
public interface IUserLoginView {
String getUserName();
String getPassword();
void clearUserName();
void clearPassword();
void showLoading();
void hideLoading();
void toMainActivity(User user);
void showFailedError();
}
//然后Activity实现这个这个接口:
public class UserLoginActivity extends ActionBarActivity implements IUserLoginView {
private EditText mEtUsername, mEtPassword;
private Button mBtnLogin, mBtnClear;
private ProgressBar mPbLoading;
private UserLoginPresenter mUserLoginPresenter = new UserLoginPresenter(this);
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_user_login);
initViews();
}
private void initViews() {
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(new View.OnClickListener() {
@Override
public void onClick(View v) {
mUserLoginPresenter.login();
}
});
mBtnClear.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mUserLoginPresenter.clear();
}
});
}
@Override
public String getUserName() {
return mEtUsername.getText().toString();
}
@Override
public String getPassword() {
return mEtPassword.getText().toString();
}
@Override
public void clearUserName() {
mEtUsername.setText("");
}
@Override
public void clearPassword() {
mEtPassword.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();
}
}
//Presenter
public class UserLoginPresenter {
private IUserBiz userBiz;
private IUserLoginView userLoginView;
private Handler mHandler = new Handler();
//Presenter必须要能拿到View和Model的实现类
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();
}
}
说明:
- Model通过回调的方式将数据传到Presenter中;
- View(Activity)负责响应用户操作,通过Presenter暴露的方法请求数据;
- Presenter在获取数据后,通过View(Activity)暴露的方法实现界面控制,通过Model来获取数据,Model包含网络、数据库以及I/O等。
采用MVP明显的优点是避免了传统开发模式中View和Model耦合的情况,提高了代码可扩展性、组件复用能力、团队协作的效率以及单元测试的便利性。但也有一些缺点,比如:
- Model到Presenter的数据传递过程需要通过回调;
- View(Activity)需要持有Presenter的引用,同时,Presenter也需要持有View(Activity)的引用,增加了控制的复杂度;
- MVC中Activity的代码很臃肿,转移到MVP的Presenter中,同样造成了Presenter在业务逻辑复杂时的代码臃肿。
所以,MVC到MVP简单说,就是增加了一个接口降低一层耦合。
MVVM
MVVM 架构模式是微软在 2005 年诞生的,MVVM是Model-View-ViewModel的简称,它由三个部分组成,也就是 Model、View 和 ViewModel,其中视图模型(ViewModel)其实就是 PM 模式中的展示模型,在 MVVM 中叫做视图模型。从实际效果来看,ViewModel是View的数据模型和Presenter的结合,具体结构如下图所示:
说明:
- Model(模型层)通过网络和本地数据库获取视图层所需数据;
- View(视图层)采用XML文件进行界面的描述;
- ViewModel(视图-模型层)负责View和Model之间的通信,以此分离视图和数据。
View和Model之间通过Android Data Binding技术,实现视图和数据的双向绑定;ViewModel持有Model的引用,通过Model的方法请求数据;获取数据后,通过Callback(回调)的方式回到ViewModel中,由于ViewModel与View的双向绑定,使得界面得以实时更新。同时,界面输入的数据变化时,由于双向绑定技术,ViewModel中的数据得以实时更新,提高了数据采集的效率。
MVVM架构将Presenter改名为ViewModel,基本上与MVP模式完全一致,唯一的区别是,它采用双向绑定(data-binding)View的变动,自动反映在 ViewModel,反之亦然,这就导致了我们如果要完整的采用 MVVM 必须熟练的掌握 DataBinding 等基础组建,这就给我们MVVM引入项目带了困难。
总结
其实,MVC、MVP及MVVM没有绝对好坏,在软件编程过程中,也没必要非此即彼,脱离实际项目比较这些模式优劣毫无意义,各种模式都有优点和缺点,没有好坏之分。越高级的架构实现起来越复杂,需要更多的学习成本更多的人力,所以说技术选型关键是在你自己项目的特点,团队的水平,资源的配备,开发时间的限制,这些才是重点!但是不少团队本末倒置,把mvvm往自己的项目硬套。最重要的是让软件高内聚、低耦合、可维护、可扩展。
可以理解为移动端的架构思维“MVX”,即是说按这个规则的分工,我们不用费尽心思考虑狭义架构的分层问题了,就沿用Model-View-X来就可以(当然还可以自己加一些辅助的模块层)。
起来越复杂,需要更多的学习成本更多的人力,所以说技术选型关键是在你自己项目的特点,团队的水平,资源的配备,开发时间的限制,这些才是重点!但是不少团队本末倒置,把mvvm往自己的项目硬套。最重要的是让软件高内聚、低耦合、可维护、可扩展。
可以理解为移动端的架构思维“MVX”,即是说按这个规则的分工,我们不用费尽心思考虑狭义架构的分层问题了,就沿用Model-View-X来就可以(当然还可以自己加一些辅助的模块层)。