大家好,我是Bin,今天为大家分享一下MVP模式在Android中的应用。目前有很多Android开发人员把复杂的业务逻辑和UI显示都写在了Activity里面,这种情况的缺点有很多,比如不方便单元测试;Activity太过臃肿;遇到需求更改的时候,Activity代码要做大量更改,代码复用性极低等。那么,如果在Android开发过程中,你巧用MVP模式,这些问题都会挥之而去。
你可能没听过MVP,没关系,MVC你总该知道吧。那么到底什么是MVP模式呢?它和MVC又有怎样的区别和联系呢?下面请看图:
MVP与MVC相同点在于:Controller/Presenter处理逻辑,Model提供数据,View负责显示。MVP与MVC最大的不同在于:在MVP中View并不直接访问Model,它们之间的通信是通过Presenter来进行的,所有的交互都发生在Presenter内部,而在MVC中View会从Model中读取数据而不是通过Controller。在MVC里,View是可以直接访问Model。
在MVP里,Presenter完全把Model和View进行了分离,主要的程序逻辑在Presenter里实现。而且,Presenter与具体的View是没有直接关联的,而是通过定义好的接口进行交互,从而使得在变更View时候可以保持Presenter的不变,即重用! 不仅如此,我们还可以编写测试用的View,模拟用户的各种操作,从而实现对Presenter的测试。
MVP的优点:
1、模型与视图完全分离,我们可以修改视图而不影响模型
2、可以更高效地使用模型,因为所有的交互都发生在Presenter内部
3、我们可以将一个Presenter用于多个视图,而不需要改变Presenter的逻辑。这个特性很关键,因为视图的变化要比模型的变化频繁的多。
4、把逻辑放在Presenter中,就可以脱离用户接口来进行单元测试
说了这么多关于MVP的东西,下面我将给出MVP模式在Android中应用的代码。
需求:
MVP模式实现的一个简单的登录Demo。用户输入用户名和密码,点击登录按钮,显示ProgressBar,进行登录,如果用户名,或密码为空,给出提示;否则登录成功,ProgressBar消失,跳转到MainActivity。
先看M层定义的接口:
package com.mobile.mvp.models;
import com.mobile.mvp.models.listenners.OnLoginFinishedListener;
public interface LoginInteractor {
public void login(String username, String password, OnLoginFinishedListener listener);
}
再看M层接口的实现:
package com.mobile.mvp.presenters;
import com.mobile.mvp.models.LoginInteractor;
import com.mobile.mvp.models.LoginInteractorImpl;
import com.mobile.mvp.models.listenners.OnLoginFinishedListener;
import com.mobile.mvp.views.LoginView;
public class LoginPresenterImpl implements LoginPresenter, OnLoginFinishedListener {
private LoginView loginView;
private LoginInteractor loginInteractor;
public LoginPresenterImpl(LoginView loginView) {
this.loginView = loginView;
this.loginInteractor = new LoginInteractorImpl();
}
@Override
public void validateCredentials(String username, String password) {
loginView.showProgress();
loginInteractor.login(username, password, this);
}
@Override
public void onUsernameError() {
loginView.setUsernameError();
loginView.hideProgress();
}
@Override
public void onPasswordError() {
loginView.setPasswordError();
loginView.hideProgress();
}
@Override
public void onSuccess() {
loginView.navigateToHome();
}
}
接着看V层接口:
package com.mobile.mvp.views;
public interface LoginView {
public void showProgress();
public void hideProgress();
public void setUsernameError();
public void setPasswordError();
public void navigateToHome();
}
V层实现:
package com.mobile.mvp.views;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ProgressBar;
import com.mobile.mvp.R;
import com.mobile.mvp.presenters.LoginPresenter;
import com.mobile.mvp.presenters.LoginPresenterImpl;
public class LoginActivity extends Activity implements View.OnClickListener, LoginView {
private EditText et_name, et_pwd;
private Button btn_login;
private ProgressBar progress;
private LoginPresenter presenter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
initView();
btn_login.setOnClickListener(this);
presenter = new LoginPresenterImpl(this);
}
private void initView() {
et_name = (EditText) findViewById(R.id.name);
et_pwd = (EditText) findViewById(R.id.pwd);
btn_login = (Button) findViewById(R.id.login);
progress = (ProgressBar) findViewById(R.id.progress);
}
@Override
public void onClick(View v) {
presenter.validateCredentials(et_name.getText().toString(), et_pwd.getText().toString());
}
@Override
public void showProgress() {
progress.setVisibility(View.VISIBLE);
}
@Override
public void hideProgress() {
progress.setVisibility(View.GONE);
}
@Override
public void setUsernameError() {
et_name.setError("用户名为空");
}
@Override
public void setPasswordError() {
et_pwd.setError("密码为空");
}
@Override
public void navigateToHome() {
startActivity(new Intent(this,MainActivity.class));
finish();
}
}
最后我们看看P层接口:
package com.mobile.mvp.presenters;
public interface LoginPresenter {
public void validateCredentials(String username, String password);
}
P层实现:
package com.mobile.mvp.presenters;
import com.mobile.mvp.models.LoginInteractor;
import com.mobile.mvp.models.LoginInteractorImpl;
import com.mobile.mvp.models.listenners.OnLoginFinishedListener;
import com.mobile.mvp.views.LoginView;
public class LoginPresenterImpl implements LoginPresenter, OnLoginFinishedListener {
private LoginView loginView;
private LoginInteractor loginInteractor;
public LoginPresenterImpl(LoginView loginView) {
this.loginView = loginView;
this.loginInteractor = new LoginInteractorImpl();
}
@Override
public void validateCredentials(String username, String password) {
loginView.showProgress();
loginInteractor.login(username, password, this);
}
@Override
public void onUsernameError() {
loginView.setUsernameError();
loginView.hideProgress();
}
@Override
public void onPasswordError() {
loginView.setPasswordError();
loginView.hideProgress();
}
@Override
public void onSuccess() {
loginView.navigateToHome();
}
}
以上就是MVP模式在Android中的应用。