目前为止,MVP的使用还没有一个标准,在此先记录一下目前学习到的一些Android中使用MVP的知识。
按传统的方式开发,经常会使Activity中混杂着UI交互,业务逻辑等流程。而MVP模式能巧妙的解决这个问题。先直接上一个小例子吧。
/**
* 定义一个对UI组件进行操作的接口,让Activity实现这个接口
* @author Quinn
* @date 2015-5-9
*/
public interface LoginView {
public void showProgress();
public void hideProgress();
public void setUsernameError();
public void setPasswordError();
public void navigateToHome();
}
/**
* Activity需要实现View接口,并且持有一个Presenter对象,将逻辑处理都转到Presenter
* @author Quinn
* @date 2015-5-9
*/
public class LoginActivity extends Activity implements LoginView,
View.OnClickListener {
private ProgressBar progressBar;
private EditText username;
private EditText password;
private LoginPresenter presenter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
progressBar = (ProgressBar) findViewById(R.id.progress);
username = (EditText) findViewById(R.id.username);
password = (EditText) findViewById(R.id.password);
findViewById(R.id.button).setOnClickListener(this);
presenter = new LoginPresenterImpl(this);
}
@Override
public void showProgress() {
progressBar.setVisibility(View.VISIBLE);
}
@Override
public void hideProgress() {
progressBar.setVisibility(View.GONE);
}
@Override
public void setUsernameError() {
username.setError(getString(R.string.username_error));
}
@Override
public void setPasswordError() {
password.setError(getString(R.string.password_error));
}
@Override
public void navigateToHome() {
startActivity(new Intent(this, MainActivity.class));
finish();
}
@Override
public void onClick(View v) {
presenter.validateCredentials(username.getText().toString(), password
.getText().toString());
}
}
/**
* Presenter接口,声明了登陆的逻辑处理接口
* @author Quinn
* @date 2015-5-9
*/
public interface LoginPresenter {
public void validateCredentials(String username, String password);
}
/**
* Presenter的具体实现,持有View和Interator的引用,处理UI响应,数据处理等
* 其中Interactor代表了Model,可以通过不同的Interactor处理各个Use case
* @author Quinn
* @date 2015-5-9
*/
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();
}
}
/**
* 处理登陆的接口
* @author Quinn
* @date 2015-5-9
*/
public interface LoginInteractor {
public void login(String username, String password, OnLoginFinishedListener listener);
}
/**
* 登陆Interactor的实现,在Presenter中持有它的引用
* @author Quinn
* @date 2015-5-9
*/
public class LoginInteractorImpl implements LoginInteractor {
@Override
public void login(final String username, final String password, final OnLoginFinishedListener listener) {
// Mock login. I'm creating a handler to delay the answer a couple of seconds
new Handler().postDelayed(new Runnable() {
@Override public void run() {
boolean error = false;
if (TextUtils.isEmpty(username)){
listener.onUsernameError();
error = true;
}
if (TextUtils.isEmpty(password)){
listener.onPasswordError();
error = true;
}
if (!error){
listener.onSuccess();
}
}
}, 2000);
}
}
/**
* 登陆结果回调接口
* @author Quinn
* @date 2015-5-9
*/
public interface OnLoginFinishedListener {
public void onUsernameError();
public void onPasswordError();
public void onSuccess();
}
稍微分析一下上面得代码接口。
View层:是图层,主要是定义一个View接口,声明各种处理UI组件的方法,然后由Activity实现,但是最后真正的调用时在Presenter中,因为在Activity中定义Presenter时将View作为构造函数的参数传递给了Presenter。
Presenter层:业务层,响应UI层,数据层,逻辑处理,持有Interactor引用。
Model/Interactor层:这里的Interactor就是Model层,它定义具体的行为接口供Presenter调用,可以实现不同的Interactor处理不同的Use case。比如数据读取,数据存储,网络请求等等操作。
参考资料:
http://antonioleiva.com/mvp-android/
https://github.com/antoniolg/androidmvp