聊聊Android开发中的MVP模式

来源:互联网 发布:手机淘宝怎么追加评论 编辑:程序博客网 时间:2024/06/05 05:39

一、初识MVP(Model View Presenter)

google上关于MVP模式的资料已经特别多了,所以我这里也不啰嗦了。
因为之前做过的几个项目,每个Activity的所有操作代码全部都是堆在里面,虽然查找还算方便,但是代码动不动就上千行,所以维护起来特别麻烦,如果代码没有注释,那对于我们来说简直就是灾难!
所以这次决定把MVP模式放在真实项目中玩玩,以下也是我从真实项目中使用的一些小感受。

二、项目实例—-【登录+注册+获取验证码+重置密码】

2.1 MVP中的Model
首先我们得建立一个存放Model的包,我这里命名为Biz。
AccountListener类中存放的都是相关操作的接口,每个接口中都有操作成功和操作失败的方法回调,至于里面的参数都可根据实际情况进行定义。

/**  * author:silencezwm on 16/6/1 10:24  * email:silencezwm@gmail.com  * description:账号监听  */public class AccountListener {    /**      * 登录监听接口      */    public interface LoginListener {        void loginSuccess();        void loginFailed(String msg);    }    /**      * 注册账号监听接口      */    public interface RegListener {        void regSuccess();        void regFailed(String msg);    }    /**      * 获取验证码监听接口      */    public interface GetVerCodeListener {        void getVerCodeSuccess();        void getVerCodeFailed(String msg);    }    /**      * 获取忘记密码验证码监听接口      */     public interface GetForgetPwdVerCodeListener {         void getForgetPwdVerCodeSuccess();         void getForgetPwdVerCodeFailed(String msg);     }    /**      * 核验验证码是否正确      */    public interface CheckVerCodeListener{        void checkVerCodeSuccess();        void checkVerCodeFailed(String msg);    }    /**      * 重置密码监听接口      */    public interface ResetPwdListener {        void resetPwdSuccess();        void resetPwdFailed(String msg);    }}

在IAccountBiz接口中定义的都是请求网络需要的参数,同样也放在Model下。

/**  * author:silencezwm on 16/6/1 11:33  * email:silencezwm@gmail.com  * description:账户相关操作所有接口Biz  */public interface IAccountBiz {    /**      *      * @param userName          用户名      * @param pwd               密码      * @param loginListener     用户登录监听      */    void login(String userName, String pwd, LoginListener loginListener);    /**      *      * @param mobile        手机号      * @param password      密码      * @param validateCode  验证码      * @param regListener   用户注册监听      */    void register(String mobile, String password, String validateCode, RegListener regListener);    /**      *      * @param mobile                手机号      * @param getVerCodeListener    获取验证码监听      */    void getVerifyCode(String mobile, GetVerCodeListener getVerCodeListener);    /**      *      * @param mobile                            手机号      * @param getForgetPwdVerCodeListener       获取忘记密码验证码监听      */    void getForgetPwdVerifyCode(String mobile,GetForgetPwdVerCodeListener getForgetPwdVerCodeListener);    /**      *      * @param mobile                手机号      * @param verCode               验证码      * @param checkVerCodeListener  核验验证码是否正确监听      */    void checkVerCode(String mobile, String verCode, AccountListener.CheckVerCodeListener checkVerCodeListener);    /**      *      * @param mobile            手机号      * @param newPwd            新密码      * @param resetPwdListener  重置密码监听      */    void resetPwd(String mobile, String newPwd, ResetPwdListener resetPwdListener);    }

Model下的AccountBiz类实现IAccountBiz接口,并显示其所有方法,这里就会进行网络请求,这里我会隐藏部分网络请求代码。

    /**      * author:silencezwm on 16/6/1 12:00      * email:silencezwm@gmail.com      * description:登录逻辑处理      */    public class AccountBiz implements IAccountBiz {        /**          *          * @param userName          用户名          * @param pwd               密码          * @param loginListener     用户登录监听          */        @Override        public void login(String userName, String pwd, final LoginListener loginListener) {            *******这里编写网络请求代码*******            -------请求成功后,调用loginListener.loginSuccess();            -------请求失败后,调用          loginListener.loginFailed(msg);             *******其他几个请求方法同上,此处省略*******        }

**到这里Model层的工作基本完成了,接下来我们瞧瞧View层。

2.2 MVP中的View
View层完全不用去管Model层做了啥,怎么做的问题,它只需要把Activity伺候好就行。
AccountView类中放在View包下,所有在Model中需要Activity提供的数据或者Model层和服务器交互后返回的数据也由View传给Activity的。

    /**      * author:silencezwm on 16/6/1 12:25      * email:silencezwm@gmail.com      * description:登录相关      */    public class AccountView {        /**          * 登录接口          */        public interface ILoginView {              /**              * @return 获取用户名              */              String getUserName();              /**               * @return 获取密码               */              String getPwd();              /**                * 登录成功后返回信息                */              void loginSuccess();              /**                * 登录失败                */              void loginFailed(String msg);        }        /**          * 获取验证码接口          */        public interface IGetVerCodeView {            /**              * @return 获取手机号              */            String getMobile();            /**              * 获取验证码成功              */            void getVerCodeSuccess();            /**              * 获取验证码失败              */            void getVerCodeFailed(String msg);        }        /**          * 获取忘记密码验证码接口          */        public interface IGetForgetPwdVerCodeView {            /**              * @return 获取手机号              */            String getMobile();            /**              * 获取忘记密码验证码成功              */            void getForgetPwdVerCodeSuccess();            /**              * 获取忘记密码验证码失败              */            void getForgetPwdVerCodeFailed(String msg);        }        /**          * 核验验证码是否正确接口          */        public interface ICheckVerCodeView {            /**              * @return 获取手机号              */            String getCheckVerCodeMobile();            /**              *              * @return  验证码              */            String getCheckVerCode();            /**              * 核验验证码成功              */            void checkVerCodeSuccess();            /**              * 核验验证码失败              */            void checkVerCodeFailed(String msg);        }        /**          * 注册接口          */        public interface IRegView {            /**              * @return 获取手机号              */            String getRegMobile();            /**              * @return 获取验证码              */            String getRegVerCode();            /**              * @return 获取密码              */            String getRegPwd();            /**              * 注册成功              */            void regSuccess();            /**              * 注册失败              */            void regFailed(String msg);        }        /**          * 重置密码          */        public interface IResetPwdView {            /**              * @return 新密码              */            String getNewPwd();            /**              * @return 手机号              */            String getMobile();            /**              * 重置密码成功              */            void resetPwdSuccess();            /**              * 重置密码失败              */            void resetPwdFailed(String msg);        }    }

到这里View层的工作也完成了,其实难度并不大,后续相关Activity只需实现View中的相关接口,并显示其中所有的方法即可

2.3 MVP中的的主角Presenter
先打个比方,牛郎和织女不是每年得相会嘛,他们中间得有座桥才行。在MVP中Model和View就像牛郎织女,而桥就是Presenter,所以正是Presenter把Model和View联系在一起的,这样也使得代码得到了解耦,各层各司其职。

    /**      * author:silencezwm on 16/6/1 12:55      * email:silencezwm@gmail.com      * description:登录Presenter      */    public class LoginPresenter {        private IAccountBiz mILoginBiz;        private ILoginView mILoginView;        //在相关Activity中实例化此Presenter,并传入相关View        public LoginPresenter(ILoginView ILoginView) {            mILoginView = ILoginView;            mILoginBiz = new AccountBiz();        }        public void login(){mILoginBiz.login(mILoginView.getUserName(), mILoginView.getPwd(), new LoginListener() {                @Override                public void loginSuccess() {                        //登录成功后,调用View的回调方法,将成功信息返回给Activity                    mILoginView.loginSuccess();                }                @Override                public void loginFailed(String msg) {                    //登录失败后,调用View的回调方法,将错误信息返回给Activity                    mILoginView.loginFailed(msg);                }            });        }    }

此时这根桥就搭建完毕了,搞了这么久,现在我们终于可以在相关Activity中进行使用了

2.4 在相关Activity中使用
1、实现相应View接口,并实现其所有方法
2、实例化Presenter,并去调用相关方法
接下来看具体代码实现:

/**  * author:silencezwm on 16/6/1 13:16  * email:silencezwm@gmail.com  * description:登录Fragment  */public class LoginFragment extends BaseFragment     implements ILoginView {@Bind(R.id.et_input_username)EditText et_input_username;@Bind(R.id.et_input_pwd)EditText et_input_pwd;private View loginView;//实例化登录相关Presenterprivate LoginPresenter mLoginPresenter = new LoginPresenter(this);        @Nullable        @Override        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {            loginView = inflater.inflate(R.layout.fragment_login, container, false);            ButterKnife.bind(this, loginView);            return loginView;        }        @OnClick({R.id.btn_login, R.id.text_forget_pwd})        public void clickOpreation(View v) {            switch (v.getId()) {                //登录                case R.id.btn_login:                    if (et_input_username.getText().toString().isEmpty()){                        ToastUtil.showToast(getActivity(), "手机号不能为空");                        return;                    }                    if (et_input_pwd.getText().toString().isEmpty()){                        ToastUtil.showToast(getActivity(), "密码不能为空");                        return;                    }                    if(!RegexUtils.checkMobile(et_input_username.getText().toString())){                        ToastUtil.showToast(getActivity(), "请输入合法的手机号");                        return;                    }                    //登录                    mLoginPresenter.login();                    break;                //忘记密码                case R.id.text_forget_pwd:                    openActivity(ForgetPwdActivity.class);                    break;            }        }        /**          * 获取输入用户名          *          * @return          */         @Override        public String getUserName() {            return et_input_username.getText().toString();        }        /**          * 获取输入密码          *          * @return          */        @Override        public String getPwd() {            return et_input_pwd.getText().toString();        }        /**          * 登录成功          */         @Override        public void loginSuccess() {            ToastUtil.showToast(getActivity(), "登录成功");        }        /**          *          * @param msg   登录失败信息          */        @Override        public void loginFailed(String msg) {            ToastUtil.showToast(getActivity(), msg);        }        @Override        public void onDestroy() {            super.onDestroy();            ButterKnife.unbind(this);        }}

三、MVP小总结
项目中使用了MVP的感受就是:

1、使用MVP后,代码量稍微多了点2、把现在Activity和之前Activity相比较,使用MVP后,Activity中的代码量大幅度下降,代码阅读、维护更方便。

另外google官方也放出了一个MVP模式的项目android-architecture,旨在引导我等开发者,并非强制我们必须按照他的模式来哦,有兴趣的可以去研究研究。

原创粉丝点击