关于mvp

说到mvp 不得不说的就是mvc 了 来先看一个经典的图

这里写图片描述

C和P的区别

1、先看C
C 就是 Controller,控制器。负责从 View 读取数据,控制用户输入,并向 Model 发送数据。简单来说,就是起到一个沟通的作用,能很大程度上的解决 Model 和 View 的耦合问题。

换句话说就是,它是一个 Model 与 View 之间的桥梁,让 Model 和 View 之间不再紧紧关联。

比如 View 接收到了用户输入数据,先交给 Controller ,Controller 再转交给 Model ,反之亦然。

但是如果controller 有问题 view 跟model 也能直接沟通

2、观察一下P

p即 Presenter 主持人。。。好 我们叫主持吧。。 作用跟跟 C 类似,仍然是负责 View 和 Model 之间的沟通。但是它彻底让 View 和 Model 不能直接沟通。如果想要沟通,就必须通过这个主持者来主持它们两个应该干啥。

比如 View 接收到了用户输入数据,不能直接给 Model ,要交给 Presenter ,Presenter 再转交给 Model ,反之亦然。

如果view接收到了用户操作必须要先交给Presenter再通过Presenter去转交给model 反过来也是 当model 改变了 也必须通过Presenter来反过来通知view去更新 不能像mvc一样model 改变view直接就能刷新了

3、简单的区别
C 和 P 都是为了解放 Model 和 View 之间的联系,只不过 C 是很大程度上解决,但 P 是彻底让它们两断了联系。

也就是c让model 、View 松散耦合,p让Model、View 解耦

来看下详细的区别

1、mvc
从下图中我们可以看到

这里写图片描述
*用户 Event(事件)会导致 Controller 改变 Model 或 View 或同时改变两者。

*只要 Controller 改变了 Model 的数据或属性,所有依赖的 View 都会自动更新。

*类似的,只要 Controller 改变了 View ,View 会从潜在的 Model 中获取数据进行更新。

2、mvp
这里写图片描述
Presenter 中同时持有 View 以及 Model 的 Interface 引用,而 View 持有 Presenter 的实例。

当某个 View 需要展示某些数据时,首先会调用 Presenter 的某个接口,然后 Presenter 会调用 Model 请求数据。

当 Model 数据加载成功后会调用 Presenter 的回调方法通知 Presenter 数据加载完毕,最后 Presenter 再调用 View 层接口展示加载后数据。

3、主要区别

在 MVC 中:

  • View 可以与 Model 直接交互;

  • Controller 可以被多个 View 共享;

  • Controller 可以决定显示哪个 View。

在 MVP 中:

  • View 不直接与 Model 交互;

  • Presenter 与 View 通过接口来交互,更有利于添加单元测试;

  • 通常 View 与 Presenter 是一对一的,但复杂的 View 可能绑定多个 Presenter 来处理;

  • Presenter 也可以直接进行 View 上的渲染。

好先看下经典的目录结构吧

这里写图片描述

好像是看不出什么来 这就是一个简单的登陆demo 万年不变
我们可以来分析一下

通过上面的介绍我们可以知道,Presenter 是用来Model 和View 之间交互的 所以必须要持有他们各自的对象

model 还要有一个业务类 这在mvc中也是一样的 索性我们就抽一个接口出来

Presenter 与view 又是通过接口来交互的所以我们就需要给view 定义一个接口

所以我们就要看到底需要什么东西

  • Model:负责检索操作数据,也就是常见的业务类对bean的操作

  • ModelInterface: 处理bean的业务逻辑接口 由bean来实现

  • view:暂时就看出activity 用来记录响应用户操作的

  • viewInterface : view 要实现用户操作的结果接口(比如登陆 界面上肯定有登陆注册按键 就要有 登陆成功失败的接口以及注册成功失败的接口)Presenter 通过 它 与view交互

  • Presenter 是个类 是用来连接view 与model的桥梁 持有二者的接口对象

  • 好吧 看起来非常多 但是逻辑确实是清晰了一点 谁是干什么的 谁控制谁响应 这种是清晰了一点。。我体会还不深 勿喷

ok 现在我们可以抽取代码了

1、bean

   /**
 * Created by MnyZhao on 2017/11/3.
 */

public class UserBean {
    /*名字*/
    private String name;
    /*密码*/
    private String passWord;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPassWord() {
        return passWord;
    }

    public void setPassWord(String passWord) {
        this.passWord = passWord;
    }
} 

2、业务操作接口 业务操作类 针对bean

UserModelInterface

/**
 * Created by MnyZhao on 2017/11/3.
 *  @description  业务操作接口 控制user的动作接口
 *  @remark
 */

public interface IUserModel {
    /*注册接口*/
    boolean onRegister(String name,String passWord);
    /*登陆接口*/
    boolean onLogin(String name,String passWord);
}

实现类 UserModel

/**
 * Created by MnyZhao on 2017/11/3.
 * model类 实现IUserModel中的动作接口
 */

public class UserModel implements IUserModel {
    private Map<String, String> userMap = new HashMap<>();

    /**
     * 注册账号放入集合
     *
     * @param name     用户名
     * @param passWord 密码
     * @return 返回是否成功(true or false)
     */
    @Override
    public boolean onRegister(String name, String passWord) {
        if (!userMap.containsKey(name)) {
            userMap.put(name, passWord);
            return true;
        }
        return false;
    }

    /**
     * 登陆接口
     *
     * @param name     用户名
     * @param passWord 密码
     * @return 是否登陆成功(true or false)
     */
    @Override
    public boolean onLogin(String name, String passWord) {
        return passWord.equals(userMap.get(name));
    }
}

3、现在我们要看看view了

ViewInterface 针对界面用户操作的相应接口

/**
 * Created by MnyZhao on 2017/11/3.
 */

public interface IUserVIew {
    //检查输入的合法性
    boolean checkInputInfo();

    //注册成功
    void onRegisterSucceed();

    //注册失败
    void onRegisterFaild();
    //登录成功
    void onLoginSucceed();

    //登录失败
    void onLoginFaild();
}

4、model view 都有了 我们就要Presenter了

Presenter类 用来沟通view 与model
所以要持有二者的接口对象

/**
 * Created by MnyZhao on 2017/11/3.
 */

public class UserPresenter {
    private IUserModel mUserModel;
    private IUserVIew mIuserView;

    public UserPresenter(IUserVIew mIuserView) {
        this.mUserModel = new UserModel();
        this.mIuserView = mIuserView;
    }

    public void registerUser(String name, String pwd) {
        //根据Model中的结果调用不同的方法进行UI展示
        if (mUserModel.onRegister(name, pwd)) {
            mIuserView.onRegisterSucceed();
        } else {
            mIuserView.onRegisterFaild();
        }
    }

    public void loginUser(String name, String pwd) {
        //根据Model中的结果调用不同的方法进行UI展示
        if (mUserModel.onLogin(name, pwd)) {
            mIuserView.onLoginSucceed();
        } else {
            mIuserView.onLoginFaild();
        }

5、接下来就要在activity(view)中实现了 需要实现view的接口(IUserVIew)并持有 Presenter的实例才能与view 进行交互

public class MainActivity extends AppCompatActivity implements IUserVIew {
    private TextInputLayout mTilName;
    private TextInputLayout mTilPassword;
    private TextInputEditText mTieName;
    private TextInputEditText mTiePassWord;
    private Button mBtnRegister, mBtnLogin;


    private UserPresenter userPeresenter;
    private String name, pwd;

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

    private void initView() {
        mTilName = (TextInputLayout) findViewById(R.id.til_name);
        mTilPassword = (TextInputLayout) findViewById(R.id.til_password);
        mTieName = (TextInputEditText) findViewById(R.id.tie_name);
        mTiePassWord = (TextInputEditText) findViewById(R.id.tie_password);
        mBtnRegister = (Button) findViewById(R.id.btn_register);
        mBtnLogin = (Button) findViewById(R.id.btn_login);
        mBtnRegister.setOnClickListener(viewListener);
        mBtnLogin.setOnClickListener(viewListener);
    }

    private View.OnClickListener viewListener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            switch (v.getId()) {
                case R.id.btn_login:
                    if (checkInputInfo()) {
                        userPeresenter.loginUser(name, pwd);
                    }
                    break;
                case R.id.btn_register:
                    if (checkInputInfo()) {
                        userPeresenter.registerUser(name, pwd);
                    }
                    break;
            }
        }
    };

    private void initUserPersenter() {
        this.userPeresenter = new UserPresenter(this);
    }

    @Override
    public boolean checkInputInfo() {
        name = mTieName.getText().toString().trim();
        pwd = mTiePassWord.getText().toString().trim();
        if (("").equals(name)) {
            mTilName.setError("Name is not null");
            return false;
        }
        if (("").equals(pwd)) {
            mTilPassword.setError("PassWord is not null");
            return false;
        }
        return true;
    }

    @Override
    public void onRegisterSucceed() {
        Toast.makeText(this, "Register Successful", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onRegisterFaild() {
        Toast.makeText(this, "Register Error", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onLoginSucceed() {
        Toast.makeText(this, "Login Successful", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onLoginFaild() {
        Toast.makeText(this, "Login Error", Toast.LENGTH_SHORT).show();
    }
}

到此 代码详细无比 只要复制粘贴就能完美运行。。哦还少一些资源文件。。等我补上

drawable

<?xml version="1.0" encoding="UTF-8"?>
<shape
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <!-- 填充的颜色 -->
    <solid android:color="#63B8FF" />
    <!-- 设置按钮的四个角为弧形 -->
    <!-- android:radius 弧形的半径 -->
    <corners android:radius="10px" />

    <!-- padding:Button里面的文字与Button边界的间隔 -->
    <padding
        android:left="20px"
        android:top="20px"
        android:right="20px"
        android:bottom="20px"
        />
</shape>


<?xml version="1.0" encoding="UTF-8"?>
<shape
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <!-- 填充的颜色 -->
    <solid android:color="#FFFFFF" />
    <!-- 设置按钮的四个角为弧形 -->
    <!-- android:radius 弧形的半径 -->
    <corners android:radius="10px" />

    <!-- padding:Button里面的文字与Button边界的间隔 -->
    <padding
        android:left="20px"
        android:top="20px"
        android:right="20px"
        android:bottom="20px"
        />
</shape> 

xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:orientation="vertical"
    android:padding="10dp"
    tools:context="com.mnyzhao.mymvpdemo.MainActivity">

    <android.support.design.widget.TextInputLayout
        android:id="@+id/til_name"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textColorHint="@color/colorAccent"
        app:errorTextAppearance="@color/colorPrimaryDark">

        <android.support.design.widget.TextInputEditText
            android:id="@+id/tie_name"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="User"
            android:textColor="@color/colorAccent"
            android:textColorHint="@color/colorAccent" />
    </android.support.design.widget.TextInputLayout>

    <android.support.design.widget.TextInputLayout
        android:id="@+id/til_password"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:textColorHint="@color/colorAccent">

        <android.support.design.widget.TextInputEditText
            android:id="@+id/tie_password"

            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="PassWord"
            android:textColor="@color/colorAccent" />
    </android.support.design.widget.TextInputLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:gravity="center"
        android:orientation="horizontal"
        android:paddingLeft="20dp"
        android:paddingRight="20dp">

        <Button
            android:id="@+id/btn_register"
            android:layout_width="match_parent"
            android:layout_height="60dp"
            android:layout_weight="1"
            android:background="@drawable/whiteshape"
            android:text="Register"
            android:textAllCaps="false"
            android:textColor="#63B8FF"
            android:textSize="18sp" />

        <Button
            android:layout_width="30dp"
            android:layout_height="wrap_content"
            android:visibility="invisible" />

        <Button
            android:id="@+id/btn_login"
            android:layout_width="match_parent"
            android:layout_height="60dp"
            android:layout_weight="1"
            android:background="@drawable/blueshape"
            android:text="Login"
            android:textAllCaps="false"
            android:textColor="@android:color/white"
            android:textSize="18sp" />

    </LinearLayout>
</LinearLayout>

如果你还不能运行 那 可能你缺少Material Design的包

compile 'com.android.support:design:25.+'

ok 如果还不行的话 那对不起 可能我不适合写代码………….

还是放上资源链接吧 不知道为什么 没有0积分的选项。。。
Demo

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值