MVP模式在项目中的使用

1.MVP模式的简介:

相对于mvc,mvp模式中p就是presenter的缩写,意思相当于主持人,它协调view和model的连接,view和model相当于是两个不认识的人,他们中间的中介就是presenter,p持有m和v两个的联系方式。view要处理页面就要要数据,就去找p,让p去拿数据。而p呢就会直接找m去要数据,m把数据给p,然后p拿着数据进行加工,然后给v有用的数据,来用于v的展示。这个过程很像我们通过中介找房子。中介有我们和出租房的联系方式,可以通过查询系统,获取到出租房的房源信息,然后给我们最后有用的信息,比如房屋价格,环境等。但是我们是和房东没有办法直接联系的。这就是mvp。而mvc的话v是可以持有model数据的,这就导致v可能会对model做数据修改。导致会掺杂一些业务逻辑。使得业务逻辑在m和c以及v中混杂到一起。这个典型的例子就是activity。既要控制显示,还要管理数据。非常混乱。而为了更好的分层,还有后续如果我换v和m都没有很大影响的话,我们就延伸出了mvp。就如那个中介,它可以换一套查询系统和房东信息,也可以换租户,但是实现的模式还是不变的。


2.MVP模式具体使用方法:

在项目中的使用:

我们通常需要以接口的形式来实现三者的关系,这样方便后续的扩展。

以登陆为例:

Model:

/**
 * 描述:登录界面请求接口
 * 
 */
public interface LoginInteractor extends MvpInteractor {
    /**
     * 登录
     * @param phone
     * @param pwd
     * @param loginInteractorListener
     */
    void userLogin(String phone, String pwd, LoginInteractorListener loginInteractorListener);
    /**
     * 请求接口监听器
     */
    interface LoginInteractorListener {
        /**
         * 请求成功且业务代码 也成功
         */
        void succeed();

        /**
         * 请求成功,但是业务代码失败
         * @param message
         */
        void failed(String message);

        /**
         * 请求失败
         *
         * @param error
         */
        void connectFail(String error);     
    }
}


View:

/**
 * 描述:
 * 作者:58 on 2016/5/11 10:41
 */
public interface LoginView extends MvpView {
    /**
     * 登录成功view显示
     */
    void loginSucceed();

    /**
     * 登录失败view显示
     * @param message
     */
    void loginFailed(String message);

    void showNotice(String message);

    void showNotice(String message);
    /**     
    * 返回当前登录界面btn的状态 
    * @param canClick  
   */  
   void isCanClick(boolean canClick);
    void loadingDismiss();
}


Presenter:

/**
 * 描述:登录界面逻辑控制器
 */
public interface LoginPresenter extends MvpPresenter<LoginView> {
    /**
     * 登录
     * @param phone
     * @param pwd
     */
    void login(String phone, String pwd, String validcode);
    /**
     * 检测是否可以点击登录btn
     * @param userPhone
     * @param password
     */
    void checkClickBtn(String userPhone, String password);
}

public interface MvpPresenter<T extends MvpView> {

    /**
     * 将MVP的View附加到Presenter
     */
    void attachView(T view);    
    void attachView(T view,ViewGroup rootView);
    void detachView();
}

具体的实现类如下:

/**
 * 描述:登录界面逻辑控制器实现
 */
public class LoginPresenterImpl implements LoginPresenter, LoginInteractor.LoginInteractorListener, GetPictureVerCodeInteractor.GetPictureVerCodeInteractorListener {
    private LoginView mLoginView;
    private Context mContext;
    private LoginInteractor mLoginInteractor;
    public LoginPresenterImpl(Context context) {
        mContext = context;
        mAccount = Account.getAccount(mContext);
    }
    @Override
    public void attachView(LoginView view) {
        mLoginView = view;
        mLoginInteractor = new LoginInteractorImpl(mContext);
    }
    @Override
    public void attachView(LoginView view, ViewGroup rootView) {
    }
    @Override
    public void detachView() {
        mLoginInteractor.cancelAllRequest();
        mContext = null;
        mLoginView = null;
    }
    @Override
    public void login(String phone, String pwd, String validcode) {
        mLoginInteractor.userLogin(phone, pwd, this);
    }
    @Override
    public void checkClickBtn(String userPhone, String password) {
        boolean canClick = !userPhone.isEmpty() && userPhone.length() == 11 && !password.isEmpty() && password.length() >= 6;
        mLoginView.isCanClick(canClick);
    }
    @Override
    public void succeed() {
        mLoginInteractor.sendPPU(this);
    }
    @Override
    public void failed(String message) {
        mLoginView.loginFailed(message);
    }
    @Override
    public void connectFail(String error) {
        mLoginView.showNotice(error);
    }
    @Override
    public void requestFinish() {
        mLoginView.loadingDismiss();
    }
}
Model:

/**
 * 描述:登录界面请求接口实现类
 */
public class LoginInteractorImpl implements LoginInteractor {
    public Context mContext;

    public LoginInteractorImpl(Context context) {
        mContext = context;
    }
    @Override
    public void cancelRequest(String requestTag) {
        HttpManager.getHttpManagerBase(mContext).cancelRequest(requestTag);
    }
    @Override
    public void cancelAllRequest() {
        HttpManager.getHttpManagerBase(mContext).cancelRequest(ConstantConfig.LOGIN_TAG);
        mContext = null;
    }
    @Override
    public void userLogin(final String phone, final String pwd, final String validcode, final String vcodekey, final LoginInteractorListener loginInteractorListener) {
        final Map<String, String> map = setParams(phone, pwd, validcode, vcodekey);
        LogUtil.i("userlogin", map.toString());
        String url = "http://test/login;   //这里只做示例
        HttpManager.getHttpManagerBase(mContext).httpPost(url, map, ConstantConfig.LOGIN_TAG, new RequestResultListener() {
            @Override
            public void onSuccess(String info, Object tag) {
                Log.e("--------------", info);
                Gson gson = new Gson();
                LoginInfo loginInfo = gson.fromJson(info, LoginInfo.class);
                if (loginInfo != null) {
                    loginInteractorListener.succeed();
                }
                loginInteractorListener.requestFinish();

            }
            @Override
            public void onFail(String code, String msg, String info, Object tag) {
              
                loginInteractorListener.failed(msg);
              
                loginInteractorListener.requestFinish();
            }
            @Override
            public void connectFail(NetworkResponse error, Object tag) {
                LogUtil.i("wuba", "connectFail");
                loginInteractorListener.connectFail("网络异常请重试");
                loginInteractorListener.requestFinish();
            }
        });
    }   
}

我们可以让我们的Activity实现View的接口即可。如下

public class LoginActivity extends BaseActivity implements LoginView {
     。。。。。此处隐去1000字大笑
public void loginSucceed() {
    ToastUtil.show(this, "登录成功");
    if (mDialog != null) {
        dialogIsShow = false;
        mDialog.dismiss();
    }
    loginIntent();

}
@Override
public void loginFailed(String message) {
    if (mDialog != null) {
        mDialog.dismiss();
        dialogIsShow = false;
    }
    if (TextUtils.isEmpty(message)) {
        message = "登陆异常,请稍后重试!";
    }
    ToastUtil.show(this, message);
}
@Override
public void showNotice(String message) {
    ToastUtil.show(this, message);
}
@Override
public void isCanClick(boolean canClick) {
    if (canClick) {
        loginLoginButton.setBackgroundResource(R.drawable.wb_login_btn_xml);
        loginLoginButton.setClickable(canClick);
    } else {
        loginLoginButton.setBackgroundResource(R.drawable.wb_unlogin_btn_xml);
        loginLoginButton.setClickable(canClick);
    }
}
@Override
public void loadingDismiss() {
    qianguiAccountLoading.statusToNormal();
    qianguiAccountLoading.setVisibility(View.GONE);
}
@Override
}
以上的代码中删去了一部分和公司相关的字段和数据,只是给大家做一个示例,不要生搬硬套。v和m的书写完全看个人的业务需求。

当我们需要替换登陆页面,或者需要替换登陆方式时,这时就会发现我们只需要动View和model即可。p就可以完全保持不动。

如果大家有什么不理解的地方,也可以给我留言。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值