1、初识MVP(Model View Presenter)android
google上关于MVP模式的资料已经特别多了,因此我这里也不啰嗦了。
由于以前作过的几个项目,每一个Activity的全部操做代码所有都是堆在里面,虽然查找还算方便,可是代码动不动就上千行,因此维护起来特别麻烦,若是代码没有注释,那对于咱们来讲简直就是灾难!
因此此次决定把MVP模式放在真实项目中玩玩,如下也是我从真实项目中使用的一些小感觉。服务器
2、项目实例----【登陆+注册+获取验证码+重置密码】网络
2.1 MVP中的Model
首先咱们得创建一个存放Model的包,我这里命名为Biz。
AccountListener类中存放的都是相关操做的接口,每一个接口中都有操做成功和操做失败的方法回调,至于里面的参数均可根据实际状况进行定义。ide
/** * 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下。this
/** * 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接口,并显示其全部方法,这里就会进行网络请求,这里我会隐藏部分网络请求代码。google
/** * 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层。.net
2.2 MVP中的View
View层彻底不用去管Model层作了啥,怎么作的问题,它只须要把Activity伺候好就行。
AccountView类中放在View包下,全部在Model中须要Activity提供的数据或者Model层和服务器交互后返回的数据也由View传给Activity的。code
/** * 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中的相关接口,并显示其中全部的方法便可blog
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中使用
一、实现相应View接口,并实现其全部方法
二、实例化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; //实例化登陆相关Presenter private 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); } }
3、MVP小总结
项目中使用了MVP的感觉就是:
一、使用MVP后,代码量稍微多了点 二、把如今Activity和以前Activity相比较,使用MVP后,Activity中的代码量大幅度降低,代码阅读、维护更方便。
另外google官方也放出了一个MVP模式的项目android-architecture,旨在引导我等开发者,并不是强制咱们必须按照他的模式来哦,有兴趣的能够去研究研究。