Android架构模式详解之MVP

MVP概念

MVP 架构是由 MVC 演变而来的,而 MVP 架构的变化是由 Presenter 来负责业务逻辑。
Presenter 层作为 Model 层和 View 层的桥梁,来实现两者的交互。Model 层依然负责的是业务逻辑和数据模型,View 层负责界面绘制和用户的交互(接受用户输入,显示请求结果)和动效等的“单一职责”。

对比MVC

先回顾下上篇文章的 Android架构模式详解之MVC 的主要内容 。
Model 用于处理数据,业务逻辑等,若数据发生变化会直接通知 View 进行改变;
View 处理 UI 的显示,动效等等;
Controller 控制 Model 的请求,获得 View 的数据返回显示,作为 View 和 Model 的桥梁分离业务逻辑和 UI 显示。

MVP 模式使得 Model 层和 View 层实现了完全解耦。View 并不直接使用 Model,它们之间的通信是通过 Presenter(MVC 中的 Controller)来进行的,所有的交互都发生在 Presenter 内部,而在 MVC 中 View 会直接从 Model 中读取数据而不是通过 Controller。
同时 Presenter 可以多次重用,方便了业务逻辑的测试。但也存在一些缺点,由于 Presenter 和 View 需要接口交互,所以会导致接口类过多。下面用表格总结一下两者关系:

类别优点缺点特点
MVC 容易理解、快速上手、使用简单 Activity 逻辑与 UI 过重将导致迭代维护困难 简单易学
MVP View 与 Model 完全隔离、Presenter 可重用、便于测试 View 层过重,需要在 Base 抽象通用 View,接口类过多,开发耗时 完全解耦

示例说明——登录界面需求

model 层代码编写

根据业务书写 Model 层的数据(用户名和密码)以及业务逻辑(登录的具体步骤),与 MVC 中的相同,这里就不贴代码了,可以参考上篇文章的 Model 层的书写。

View 层代码编写

定义接口,因为 Presenter 需要接口与 View 交互的接口方法。接口中方法的定义,编写的思路可以按照下面的方法:

  • 该操作需要什么?
  • 该操作的结果,对应的反馈?(success, failed)
  • 该操作过程中对应的友好的交互?(showLoading, hideLoading)
//Presenter 和 View 的交互,通过该接口实现
public interface LoginView {
    void showLoading();
    void hideLoading();
    void success();
    void failed();
}

Presenter 层代码编写

作为 View 和 Model 之间交互的桥梁,包含的方法主要还是看该功能有什么操作,同时完成两者的交互,就需要二者的实现类,从 View 中获取需要的参数,然后交给 Model 去执行业务方法。执行过程中需要的反馈和结果,再让 View 进行对应的显示。

public class LoginPresenter {

    private LoginView mLoginView;
    private LoginModel model;
    private Context mContext;

    public LoginPresenter(Context context, LoginView mLoginView) {
        this.mLoginView = mLoginView;
        model = new LoginModelImpl();
        this.mContext = context;
    }

    public void login(String account,String password) {
        if (TextUtils.isEmpty(account)||TextUtils.isEmpty(password)){
            Toast.makeText(mContext,"请输入账号和密码!",Toast.LENGTH_SHORT).show();
        }else {
            mLoginView.showLoading();
            model.login(account, password, new LoginListener() {
                @Override
                public void success() {
                    mLoginView.success();
                    mLoginView.hideLoading();
                }

                @Override
                public void error() {
                    mLoginView.failed();
                    mLoginView.hideLoading();
                }
            });
        }

    }

}

在 Activity 中的代码如下:

public class MainActivity extends AppCompatActivity implements View.OnClickListener,LoginView{

    private EditText editAccount,editPassword;
    private Button loginBtn,clearBtn;
    private ProgressDialog dialog;
    private LoginPresenter loginPresenter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initViews();
    }

    private void initViews() {
        editAccount = (EditText) findViewById(R.id.edit_account);
        editPassword = (EditText) findViewById(R.id.edit_pwd);
        loginBtn = (Button) findViewById(R.id.btn_login);
        clearBtn = (Button) findViewById(R.id.btn_reset);

        dialog = new ProgressDialog(this);
        dialog.setMessage("正在登陆,请稍后...");
        dialog.setCanceledOnTouchOutside(false);

        loginPresenter = new LoginPresenter(this,this);
        initListener();
    }

    private void initListener() {
        loginBtn.setOnClickListener(this);
        clearBtn.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.btn_login:
                loginPresenter.login(editAccount.getText().toString(),editPassword.getText().toString());
                break;
            default:
                break;
        }
    }

    @Override
    public void showLoading() {
        dialog.show();
    }

    @Override
    public void hideLoading() {
        dialog.dismiss();
    }

    @Override
    public void success() {
        Toast.makeText(this,"登陆成功!",Toast.LENGTH_SHORT).show();
    }

    @Override
    public void failed() {
        Toast.makeText(this,"登陆失败!",Toast.LENGTH_SHORT).show();
    }

}

这样的架构在项目代码中显得逻辑更加清晰,样式更加简洁。这是 MVP 架构带来的直观感受。
在下一篇文章 Android架构模式的简单封装,我们会做一些 MVP 的简单封装来优化 MVP 的使用。

posted @ 2017-04-27 12:03  天涯海角路  阅读(290)  评论(0)    收藏  举报