Android进阶-MVP

一、什么是MVP?

MVP (Model View Presenter)模式由MVC模式演变而来,它将View层和逻辑层分离。

二、为什么使用MVP?

将View层和逻辑层分离后有利于拓展,比如当前代码属于来自本地数据库,如果需求变更数据来自网络,我们就不必重写整个View层。通过MVP我们将大部分逻辑抽出Activity,写在Presenter层。分层后就可以各司其职,也方便测试。

三、各层的职责。

  1. Presenter的职责:从Modle层获取数据经过处理后交给View层展示。
  2. View的职责:MVP将Activity划在View层,Activity引用Presenter。View层主要有两个任务。1.对外提供修改控件属性的接口。2.响应外部事件,交给Presenter处理。这样Activity的任务就很明确了。
  3. Model的职责:提供给Presenter需要的数据。

四、实例.

一个登陆的例子(项目代码在这里下载:https://github.com/gatsbydhn/androidmvp):

View层:

View接口,Activity实现了该接口,方便以后拓展:

 1 public interface LoginView {
 2     void showProgress();
 3 
 4     void hideProgress();
 5 
 6     void setUsernameError();
 7 
 8     void setPasswordError();
 9 
10     void navigateToHome();
11 }

Activity:

 1 public class LoginActivity extends Activity implements LoginView, View.OnClickListener {
 2 
 3     private ProgressBar progressBar;
 4     private EditText username;
 5     private EditText password;
 6     private LoginPresenter presenter;
 7 
 8     @Override
 9     protected void onCreate(Bundle savedInstanceState) {
10         super.onCreate(savedInstanceState);
11         setContentView(R.layout.activity_login);
12 
13         progressBar = (ProgressBar) findViewById(R.id.progress);
14         username = (EditText) findViewById(R.id.username);
15         password = (EditText) findViewById(R.id.password);
16         findViewById(R.id.button).setOnClickListener(this);
17 
18         presenter = new LoginPresenterImpl(this);
19     }
20 
21     @Override protected void onDestroy() {
22         presenter.onDestroy();
23         super.onDestroy();
24     }
25 
26     @Override public void showProgress() {
27         progressBar.setVisibility(View.VISIBLE);
28     }
29 
30     @Override public void hideProgress() {
31         progressBar.setVisibility(View.GONE);
32     }
33 
34     @Override public void setUsernameError() {
35         username.setError(getString(R.string.username_error));
36     }
37 
38     @Override public void setPasswordError() {
39         password.setError(getString(R.string.password_error));
40     }
41 
42     @Override public void navigateToHome() {
43         startActivity(new Intent(this, MainActivity.class));
44         finish();
45     }
46 
47     @Override public void onClick(View v) {
48         presenter.validateCredentials(username.getText().toString(), password.getText().toString());
49     }
50 }

分析:如前面所说Activilty里面的方法分为两类:1.修改控件属性如showProgress(),hideProgress()等,这些接口将被Presenter调用。2.响应外部事件比如onClick(),onDestroy()等,调用Presenter来完成具体的任务。

下面是Presenter层:

接口,方便拓展:

1 public interface LoginPresenter {
2     void validateCredentials(String username, String password);
3 
4     void onDestroy();
5 }

实现类:

 1 public class LoginPresenterImpl implements LoginPresenter, LoginInteractor.OnLoginFinishedListener {
 2 
 3     private LoginView loginView;
 4     private LoginInteractor loginInteractor;
 5 
 6     public LoginPresenterImpl(LoginView loginView) {
 7         this.loginView = loginView;
 8         this.loginInteractor = new LoginInteractorImpl();
 9     }
10 
11     @Override public void validateCredentials(String username, String password) {
12         if (loginView != null) {
13             loginView.showProgress();
14         }
15 
16         loginInteractor.login(username, password, this);
17     }
18 
19     @Override public void onDestroy() {
20         loginView = null;
21     }
22 
23     @Override public void onUsernameError() {
24         if (loginView != null) {
25             loginView.setUsernameError();
26             loginView.hideProgress();
27         }
28     }
29 
30     @Override public void onPasswordError() {
31         if (loginView != null) {
32             loginView.setPasswordError();
33             loginView.hideProgress();
34         }
35     }
36 
37     @Override public void onSuccess() {
38         if (loginView != null) {
39             loginView.navigateToHome();
40         }
41     }
42 }

分析:这里使用面向接口编程,方便以后拓展。Presenter引用Model层的LoginInteractor,完成View交给的任务validateCredentials(),该方法中调用LoginInteractor获取登陆数据。

Model层:

接口:

 1 public interface LoginInteractor {
 2 
 3     interface OnLoginFinishedListener {
 4         void onUsernameError();
 5 
 6         void onPasswordError();
 7 
 8         void onSuccess();
 9     }
10 
11     void login(String username, String password, OnLoginFinishedListener listener);
12 
13 }

实现类:

 1 public class LoginInteractorImpl implements LoginInteractor {
 2 
 3     @Override
 4     public void login(final String username, final String password, final OnLoginFinishedListener listener) {
 5         // Mock login. I'm creating a handler to delay the answer a couple of seconds
 6         new Handler().postDelayed(new Runnable() {
 7             @Override public void run() {
 8                 boolean error = false;
 9                 if (TextUtils.isEmpty(username)){
10                     listener.onUsernameError();
11                     error = true;
12                 }
13                 if (TextUtils.isEmpty(password)){
14                     listener.onPasswordError();
15                     error = true;
16                 }
17                 if (!error){
18                     listener.onSuccess();
19                 }
20             }
21         }, 2000);
22     }
23 }

分析:登陆应该要从数据库获取数据验证账号密码是否正确,这里省略了这一步骤,但是要明白,这一层的职责是提供数据,不管是从数据库还是网络。

posted @ 2016-04-10 10:00  gatsbydhn  阅读(310)  评论(0编辑  收藏  举报