MVP浅析

1.MVP

Model-view-presenter (MVP) 是使用者接口设计模式的一种。 随着UI创建技术的功能日益增强,UI层也履行着越来越多的职责。为了更好地细分视图(View)与模型(Model)的功能,让View专注于处理数据的可视化以及与用户的交互,同时让Model只关系数据的处理,基于MVC概念的MVP 模式应运而生。

说明:
M层 对P层传递过来的信息(userInfo进行登录(网络请求))处理,处理完成之后将处理结果回调给P层

V层 负责响应用户的交互(获取数据—->提示操作结果)

P层 传递完数据给M层处理之后,实例化回调对象,成功了就通知V层登录成功,并将相关信息传给V层 ,失败了就通知V层显示错误信息,即数据逻辑的处理在P层,也相当于一个控制器,起到纽带的作用,这样也就使得M 层和V 层处于一个完全分离的状态,更好地专注其自身层的业务。

网上的这张图片说得更直观
这里写图片描述

2.MVP的优点编辑

1、模型与视图完全分离,我们可以修改视图而不影响模型
2、可以更高效地使用模型,因为所有的交互都发生在一个地方——Presenter内部
3、我们可以将一个Presenter用于多个视图,而不需要改变Presenter的逻辑。这个特性非常的有用,因为视图的变化总是比模型的变化频繁。
4、如果我们把逻辑放在Presenter中,那么我们就可以脱离用户接口来测试这些逻辑(单元测试)

3.举个栗子

无图无真相,我们这是无代码无真理,下面简单地尝试实现一个用mvp 实现的登陆小栗子(ps:网上很多例子也是从登陆开始,估计比较简单吧)。

1.布局代码(用ConstraintLayout)

布局比较简单,可以直接忽略

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#ECEDF1">

    <TextView
        android:id="@+id/tv_login_title"
        android:layout_width="384dp"
        android:layout_height="wrap_content"
        android:background="#12B7F5"
        android:gravity="center"
        android:padding="20dp"
        android:text="添加账号"
        android:textColor="#ffffff"
        android:textSize="18sp"
        tools:ignore="HardcodedText,MissingConstraints"
        tools:layout_editor_absoluteX="0dp"
        tools:layout_editor_absoluteY="0dp" />

    <TextView
        android:id="@+id/tv_login_cancel"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="#00000000"
        android:padding="20dp"
        android:text="取消"
        android:textColor="#ffffff"
        app:layout_constraintHorizontal_bias="0.99"
        app:layout_constraintLeft_toLeftOf="@+id/tv_login_title"
        app:layout_constraintRight_toRightOf="@+id/tv_login_title"
        tools:ignore="HardcodedText,MissingConstraints"
        tools:layout_editor_absoluteY="0dp" />

    <EditText
        android:id="@+id/et_login_name"
        android:layout_width="0dp"
        android:layout_height="32dp"
        android:layout_marginBottom="16dp"
        android:layout_marginTop="12dp"
        android:background="#ffffff"
        android:ems="10"
        android:hint="账号/手机号/邮箱"
        android:inputType="textPersonName"
        android:paddingLeft="12dp"
        android:paddingRight="12dp"
        android:textSize="12sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintHorizontal_bias="1.0"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="@+id/tv_login_title"
        app:layout_constraintVertical_bias="0.13"
        tools:ignore="HardcodedText,LabelFor,MissingConstraints,RtlHardcoded" />

    <EditText
        android:id="@+id/et_login_password"
        android:layout_width="0dp"
        android:layout_height="32dp"
        android:layout_marginBottom="16dp"
        android:layout_marginTop="2dp"
        android:background="#ffffff"
        android:ems="10"
        android:hint="密码"
        android:inputType="textPassword"
        android:paddingLeft="12dp"
        android:paddingRight="12dp"
        android:textSize="12sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/et_login_name"
        app:layout_constraintVertical_bias="0.0"
        tools:ignore="HardcodedText,LabelFor" />

    <Button
        android:id="@+id/btn_login_to_login"
        android:layout_width="0dp"
        android:layout_height="48dp"
        android:layout_marginBottom="16dp"
        android:layout_marginEnd="8dp"
        android:layout_marginLeft="8dp"
        android:layout_marginRight="8dp"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        android:background="@drawable/login_login_button_bg"
        android:text="登  陆"
        android:textColor="#ffffff"
        android:textSize="14sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintHorizontal_bias="0.56"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/et_login_password"
        app:layout_constraintVertical_bias="0.03"
        tools:ignore="HardcodedText" />

    <CheckBox
        android:id="@+id/checkBox"
        android:layout_width="wrap_content"
        android:layout_height="32dp"
        android:layout_marginBottom="16dp"
        android:layout_marginEnd="16dp"
        android:layout_marginStart="16dp"
        android:layout_marginTop="8dp"
        android:text="@string/cb_login_agree"
        android:textSize="8sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintHorizontal_bias="0.0"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/btn_login_to_login"
        app:layout_constraintVertical_bias="0.03"
        tools:ignore="MissingConstraints,SmallSp" />

</android.support.constraint.ConstraintLayout>

2.我们先看下包结构

简单的包结构如下:
这里写图片描述

各层次包名还算比较清晰,就不多说了。需要说明下,请求网络验证用户信息并没有做,只是做了模拟。

1.UserInfo.java 普通的bean,只有userName和userPassword字段以及get 和set方法。

2.ILoginModel.java
从名字上看就知道是 M层的接口,实现了登陆功能,代码如下

public interface ILoginModel {
//登录
    void login(UserInfo userInfo, Result result);
}

3.LoginModel.java
M层接口实现类,负责处理网络请求返回相应结果

public class LoginModel implements ILoginModel {
    @Override
        public void login(UserInfo userInfo, Result result) {
        //模拟时延
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //模拟网络请求部分
        if("XX".equals(userInfo.getUserName())&&"123".equals(userInfo.getUserPassword())){
            result.success();
        }else {
            result.error();
        }
    }

4.Reset.java
模拟网络请求结果返回

public interface Result {
    void success();
    void error();
}

5.ILoginPresenter.java
P 层接口,联通V 和M 层的桥梁。

public interface ILoginPresenter {
    void login();
}

6.LoginPresenter.java
P层接口实现类,相关逻辑在此处理

public class LoginPresenter implements ILoginPresenter {
    private ILoginModel loginModel;
    private ILoginView loginView;
    public LoginPresenter( ILoginView loginView) {
        this.loginModel = new LoginModel();
        this.loginView = loginView;
    }

    @Override
    public void login() {
        if(TextUtils.isEmpty(loginView.getUserLoginInfo().getUserName())){
            loginView.showErrorMsg("用户名不能为空");
            return;
        }
        if(TextUtils.isEmpty(loginView.getUserLoginInfo().getUserPassword())){
            loginView.showErrorMsg("密码不能为空");
            return;
        }
        loginModel.login(loginView.getUserLoginInfo(), new Result() {
            @Override
            public void success() {
                loginView.showInfo("登陆成功!");

            }
            @Override
            public void error() {
                loginView.showErrorMsg("错误");
            }
        });
    }
}

7.ILoginView.java
V层接口,View需要显示和用户响应操作都在这里。

public interface ILoginView {
    void showInfo(String info);//提示用户
    void showErrorMsg(String msg);//发生错误就显示错误信息
    UserInfo getUserLoginInfo();//获取用户登录信息
}

8.MainActivity.java
V层实现类,也就是我们activity。

public class MainActivity extends AppCompatActivity implements ILoginView{

    @Bind(R.id.et_login_name)
    EditText etLoginName;
    @Bind(R.id.et_login_password)
    EditText etLoginPassword;

    //一个p对象
    private LoginPresenter presenter;
    private Context mContext;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ButterKnife.bind(this);
        mContext = this;
        presenter = new LoginPresenter(this);

    }

    @OnClick({R.id.tv_login_cancel, R.id.btn_login_to_login, R.id.checkBox})
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.tv_login_cancel:
                finish();
                break;
            case R.id.btn_login_to_login:
                presenter.login();
                break;
            case R.id.checkBox:
                break;
        }
    }

    @Override
    public void showInfo(String info) {
        Toast.makeText(mContext,"登陆"+info,Toast.LENGTH_SHORT).show();
    }

    @Override
    public void showErrorMsg(String msg) {
        Toast.makeText(mContext,"登陆错误"+msg,Toast.LENGTH_SHORT).show();
    }

    @Override
    public UserInfo getUserLoginInfo() {
        return new UserInfo(etLoginName.getText().toString().trim()
                ,etLoginPassword.getText().toString().trim());
    }
}

一个简单mvp 模式的小栗子基本到这里就结束了,里面用到了ConstraintLayout布局和ButterKnife,需要在gradle 依赖中引入如下代码:
compile ‘com.android.support.constraint:constraint-layout:1.0.0-alpha9’
compile ‘com.jakewharton:butterknife:7.0.1’

源码下载

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值