Android MVP 设计模式

这篇文章参照Hongyang的博客整理。
浅谈 MVP in Android

MVP设计模式

何为MVP

1.View 对应于Activity,负责View的绘制以及与用户交互
2.Model 依然是业务逻辑和实体模型
3.Presenter 负责完成View于Model间的交互

Presenter 在这里类似于一个主持人的角色,他负责Model实体类与VIEW表示层的交互,这个交互通常使用接口实现

MVP的特征

  • Presenter是整个MVP体系的控制中心,而不是单纯的处理View请求的人;

  • View仅仅是用户交互请求的汇报者,对于响应用户交互相关的逻辑和流程,View不参与决策,真正的决策者是Presenter;

  • View向Presenter发送用户交互请求应该采用这样的口吻:“我现在将用户交互请求发送给你,你看着办,需要我的时候我会协助你”,不应该是这样:“我现在处理用户交互请求了,我知道该怎么办,但是我需要你的支持,因为实现业务逻辑的Model只信任你”;

  • 对于绑定到View上的数据,不应该是View从Presenter上“拉”回来的,应该是Presenter主动“推”给View的;

  • View尽可能不维护数据状态,因为其本身仅仅实现单纯的、独立的UI操作;Presenter才是整个体系的协调者,它根据处理用于交互的逻辑给View和Model安排工作。

这里写图片描述
转变成
这里写图片描述

MVC设计模式

1. View:对应于布局文件
2. Model:业务逻辑和实体模型
3. Controllor:对应于Activity
MVC与MVP的不同

MVP与MVC最大的不同是Model不能和VIEW直接通信,必须经过Persenter(主持者)
这里写图片描述

MVP 示例演示

这是模拟登陆的一个demo,使用接口实现MVP设置,在这个demo中,主Activity并没有直接调用Login的业务逻辑(Login的业务逻辑应写在user-Model中),而是使用Persenter通过接口实现login流程,通过接口实现可以进一步解耦。
这里写图片描述

代码结构

这里写图片描述

布局文件
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.mvp_pattern.MainActivity" >

    <EditText
        android:id="@+id/id_et_username"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />


    <EditText
        android:id="@+id/id_et_pwd"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <Button
        android:id="@+id/id_btn_submit"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Login" />

    <ProgressBar
        android:id="@+id/id_pb_loading"
        style="@android:style/Widget.ProgressBar.Inverse"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:visibility="gone" />

</LinearLayout>

下面是Model层

User类

public class User {
    private String username;
    private String password;
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }


}

User模型的登录流程写在BIZ 包中,也属于MODEL

public interface IUserBIZ {
    void login(String username, String password, OnLoginListener listener);
}
public interface OnLoginListener {
    void loginSuccess(User user);

    void loginFail();
}

登录流程

public class UserBIZ implements IUserBIZ {

    @Override
    public void login(final String username, final String password,
            final OnLoginListener listener) {
        // 使用子线程模拟耗时操作
        new Thread() {
            @Override
            public void run() {
                try {
                    sleep(2000);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                // 判断是否登录成功
                if (username.equals("ytr") && password.equals("123")) {
                    User user = new User();
                    user.setUsername(username);
                    user.setPassword(password);
                    if (listener != null) {
                        listener.loginSuccess(user);
                    }
                } else {
                    if (listener != null) {
                        listener.loginFail();
                    }
                }
            };
        }.start();

    }

}

VIEW层,用于描述界面,需用接口进行约束,只后用于和Presenter交互

// 登录界面需实现的接口
public interface IUserLoginView {
    String getUserName();

    String getPassword();

    void clearUserName();

    void clearPassword();

    void showLoading();

    void hideLoading();

    void toMainActivity();

    void showFailError();
}

Persenter 交互核心,通过接口实现Model和View的交互

// presenter角色,是Model和View交互的桥梁
public class LoginPresenter {
    private IUserBIZ mUserBIZ;
    private IUserLoginView mLoginView;
    // 用于在UI线程中更新UI
    private Handler mHandler = new Handler();

    public LoginPresenter(IUserLoginView loginView) {
        mLoginView = loginView;
        mUserBIZ = new UserBIZ();
    }

    public void login() {
        mLoginView.showLoading();
        mUserBIZ.login(mLoginView.getUserName(), mLoginView.getPassword(),
                new OnLoginListener() {

                    @Override
                    public void loginSuccess(User user) {
                        // 在UI线程更新UI
                        mHandler.post(new Runnable() {

                            @Override
                            public void run() {
                                mLoginView.toMainActivity(); // 登录操作
                                mLoginView.hideLoading();
                            }
                        });

                    }

                    @Override
                    public void loginFail() {
                        mHandler.post(new Runnable() {

                            @Override
                            public void run() {
                                mLoginView.showFailError(); // 登录操作
                                mLoginView.hideLoading();
                            }
                        });
                    }
                });
    }

    public void clear() {
        mLoginView.clearPassword();
        mLoginView.clearUserName();
    }
}

Activity和LoginPresenter交互 M–V–P交互的实现


public class MainActivity extends ActionBarActivity implements IUserLoginView {

    private EditText mEtUser;
    private EditText mEtPwd;
    private Button mBtnLogin;
    private ProgressBar mPbLoading;
    private LoginPresenter mPresenter = new LoginPresenter(this);

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mEtUser = (EditText) findViewById(R.id.id_et_username);
        mEtPwd = (EditText) findViewById(R.id.id_et_pwd);
        mBtnLogin = (Button) findViewById(R.id.id_btn_submit);
        mPbLoading = (ProgressBar) findViewById(R.id.id_pb_loading);
        mBtnLogin.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View arg0) {
                // 登录操作
                mPresenter.login();
            }
        });
    }


    @Override
    public String getUserName() {
        return mEtUser.getText().toString();
    }

    @Override
    public String getPassword() {
        return mEtPwd.getText().toString();
    }

    @Override
    public void clearUserName() {
        mEtUser.setText("");
    }

    @Override
    public void clearPassword() {
        mEtPwd.setText("");
    }

    @Override
    public void showLoading() {
        mPbLoading.setVisibility(View.VISIBLE);
    }

    @Override
    public void hideLoading() {
        mPbLoading.setVisibility(View.GONE);

    }

    @Override
    public void toMainActivity() {
        Toast.makeText(this, "toMainActivity()", Toast.LENGTH_SHORT).show();

    }

    @Override
    public void showFailError() {
        Toast.makeText(this, "LoginFail", Toast.LENGTH_SHORT).show();

    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值