zoukankan      html  css  js  c++  java
  • 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 }

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

  • 相关阅读:
    python 输入和输出
    python 深入模块和包
    python 模块
    python 字典 注意点
    javaNIO核心概念
    redis使用bit做只有两种情况的“状态“统计(如是否在线的用户统计)
    mysqlbinlog二三事儿
    mysql在windows下的服务安装
    javassist标识符
    使用redis调用lua脚本的方式对接口进行限流
  • 原文地址:https://www.cnblogs.com/gatsbydhn/p/5373444.html
Copyright © 2011-2022 走看看