聊聊Android開發中的MVP模式



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


相關文章
相關標籤/搜索