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,旨在引導我等開發者,並不是強制咱們必須按照他的模式來哦,有興趣的能夠去研究研究。