Android MVP框架

尝试使用MVP框架实现一个登陆的demo,记录一下。

首先说一下MVP框架的各层的职责。

Module层负责用户数据,如数据库的查询,网络查询等。

View层负责更新UI界面,向外部提供更新UI的接口,在Activity或者Fragment中进行实现。

Presenter层负责逻辑的操作,将Module和View层关联起来,向外提供逻辑接口和实现类,在Activity或者Fragment中可直接进行调用。

View和Presenter的实例需要相互绑定。大致的关系:View⇔Presenter←Module

下面用MVP框架实现一个用户登陆的模型。

代码结构如图:


View层提供的接口用于去更新UI控件,首先需要考虑一下都在什么情况下需要更新UI。

1.当登陆开始的时候需要显示progressbar

2.当登陆成功/失败时需要显示toast

3.当点击清除按钮时需要将EditText中的用户数据清空

上记情况整理出来之后就可以提取出下面的接口了。

该接口的实现是在Activity或者Fragment中进行实现,在Presenter中进行调用。

public interface ILoginView {

    /**
     * Login开始
     */
    void onLoginStart();

    /**
     * Login成功
     */
    void onLoginSuccess();

    /**
     * Login失败
     */
    void onLoginFail();


    /**
     * 清除数据
     */
    void onClearView();
}
Presenter提供的接口用于提供逻辑处理,逻辑处理只有两个,一个是用户点击登陆按钮;一个是用户点击清除按钮。

所以Presenter只需要向View层提供两个方法进行调用即可。

public interface ILoginPresenter {

    /**
     * 登录处理
     * @param username
     * @param password
     */
    void onLogin(String username, String password);

    /**
     *清除处理
     */
    void onClear();
}
Module层提供的接口用于提供用户数据的操作,此处只是简单提供了一个校验的方法,如果需要查询数据库或者访问网络,也需要在Module层处理。

public interface IUser {
    boolean checkUserInfo(String username, String password);
}


接口整理出来之后实现就很简单了,直接贴代码。

View的实现在Activity中

@Override
    public void onLoginStart() {
        mProgressBar.setVisibility(View.VISIBLE);
    }

    @Override
    public void onLoginSuccess() {
        mProgressBar.setVisibility(View.GONE);
        Toast.makeText(this, R.string.login_success, Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onLoginFail() {
        mProgressBar.setVisibility(View.GONE);
        Toast.makeText(this, R.string.login_fail, Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onClearView() {
        mUserName.setText("");
        mPassword.setText("");
    }

Presenter的实现

public class LoginPresenterImp implements ILoginPresenter {

    private ILoginView mLoginView;
    private LoginHandler mHandler;

    private static final int LOGIN_SUCCESS = 1;
    private static final int LOGIN_FAIL = 2;

    public LoginPresenterImp(ILoginView mLoginView) {
        this.mLoginView = mLoginView;
        mHandler = new LoginHandler();
    }

    @Override
    public void onLogin(final String username, final String password) {
        mLoginView.onLoginStart();
        new Thread() {
            @Override
            public void run() {
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                IUser user = new UserImp(username, password);

                Message message = new Message();
                if (user.checkUserInfo(username, password)) {
                    message.what = LOGIN_SUCCESS;
                } else {
                    message.what = LOGIN_FAIL;
                }
                mHandler.sendMessage(message);
            }
        }.start();
    }

    @Override
    public void onClear() {
        mLoginView.onClearView();
    }

    class LoginHandler extends Handler{
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case LOGIN_SUCCESS:
                    mLoginView.onLoginSuccess();
                    break;
                case LOGIN_FAIL:
                    mLoginView.onLoginFail();
                    break;
                default:
                    break;
            }
        }
    }
}

还剩下最后一步,就是三者之间的相互调用

View和Presenter之间是需要相互绑定的,所以在Activity中new一个Presenter实例,并将自己绑定到Presenter中

mLoginPresenter = new LoginPresenterImp(this);
这样在Activity中可以调用Presenter实例进行逻辑处理。

public void onClick(View v) {
        switch (v.getId()) {
            case R.id.login:
                String username = mUserName.getText().toString();
                String password = mPassword.getText().toString();
                mLoginPresenter.onLogin(username, password);
                break;
            case R.id.clear:
                mLoginPresenter.onClear();
                break;
            default:
                break;
        }
    }

同时把实现view接口的自己本身绑定到了Presenter中,从而在Presenter在逻辑处理完成后,可以通过调用view的接口进行UI的更新。

class LoginHandler extends Handler{
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case LOGIN_SUCCESS:
                    mLoginView.onLoginSuccess();
                    break;
                case LOGIN_FAIL:
                    mLoginView.onLoginFail();
                    break;
                default:
                    break;
            }
        }
    }
需要注意一下子线程不能直接更新UI的问题

Presenter中可以在需要时可以new User实例,调用User的方法进行用户数据的操作,本例是调用user的checkUserInfo的方法

IUser user = new UserImp(username, password);

Message message = new Message();
if (user.checkUserInfo(username, password)) {
    message.what = LOGIN_SUCCESS;
} else {
    message.what = LOGIN_FAIL;
}


基本上就是以上的流程,比较难的地方在于一开始对于通过整理各层担当,从而提取出各层的接口。接口提取出来之后整个逻辑框架就会变的很清晰了。






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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值