<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Android中MVC與MVP框架實例解析

          共 8716字,需瀏覽 18分鐘

           ·

          2021-04-25 12:51

          首先先明確一下MVC和MVP到底是設(shè)計模式還是框架?


          設(shè)計模式是從coding層面提煉出來的一種總結(jié),用來使得代碼的耦合度達到最大限度的分離,從而可以使你的代碼更好的被復(fù)用,更容易被替換,更好的擁抱需求的變化。


          架構(gòu)則是著眼于更全局的高度,是保證軟件的可用性,可擴展性,可伸縮性,安全等等一系列的指標(biāo)。


          設(shè)計模式服務(wù)于架構(gòu),是實現(xiàn)架構(gòu)設(shè)計的具體手段,架構(gòu)是從整體上著手設(shè)計具有宏觀性。


          所以說MVC和MVP是一種框架架構(gòu)模式,不是設(shè)計模式。


          一 MVC:


          是一種經(jīng)典的三層架構(gòu)模式,目的是將數(shù)據(jù)層和視圖層分離,使它們的耦合度降低,符合面向?qū)ο笤O(shè)計的單一原則。


          M:Model(數(shù)據(jù)層),實體模型,包含網(wǎng)絡(luò)請求、數(shù)據(jù)庫讀取、文件讀取、邏輯運算、業(yè)務(wù)bean類等等,實際中常用來對數(shù)據(jù)的封裝和保存。


          V:View(視圖層),視圖界面,對應(yīng)于布局文件,更具體的就是視圖控件,例如:TextView、ImageView等等。


          C:Controller(控制層),將model數(shù)據(jù)展示在view上,控制應(yīng)用程序的流程,業(yè)務(wù)邏輯的處理;對應(yīng)于工程宏的Activity、Fragment、Adapter等。


          優(yōu)點:

          • 站在Android的角度看個人認(rèn)為,MVC適用于中小型項目的開發(fā),其開發(fā)周期短,效率高,模塊職責(zé)劃分明確。

          • 主要劃分層M,V,C三個模塊,利于代碼的維護。


          缺點:雖然MVC將數(shù)據(jù)、視圖、控制器劃分三層看似層與層之間是耦合度降低了,但是實際開發(fā)中并沒有起到完全的解耦。因為View對應(yīng)的XML文件實際能做的事情很少,很多界面顯示由Controllor對應(yīng)的Activity或者Fragment給做了,導(dǎo)致View和Controller之間的分層很模糊,也就是Activity充當(dāng)Controllor也充當(dāng)了View,也就造成Activity的職責(zé)不清,導(dǎo)致Controllor層非常的臃腫,也進一步導(dǎo)致了耦合度非常的高。


          二 MVP:


          基于MVC衍生出來的一種模式,將MVC中的C優(yōu)化成了P,P負(fù)責(zé)業(yè)務(wù)核心邏輯,并阻斷了View和Model的直接聯(lián)系,從而使View和Model更加專注自身的邏輯。適合中大型項目。


          MVP實際上是使View變薄,View和Model完全解耦。


          M:和MVC中的M是一樣。


          V:Activity、Fragment,View會包含一個或者多個P的引用用P的邏輯,P也可以控制V的顯示。


          P(Presenter):作為V和M的橋梁,負(fù)責(zé)從M中拿數(shù)據(jù)處理后返所以每個P通常包含一個或者多個接口協(xié)議。


          優(yōu)點:

          • View和 Model之間的耦合度降低,結(jié)構(gòu)清晰,維護方便。

          • 便于單元測試。

          • 代碼復(fù)用率高,擴展性強。

          • 代碼框架更適用于快速迭代開發(fā)。


          缺點:

          • 類相對較多,如果一個Presenter被多個View引用,那么每個View中都要創(chuàng)建Presenter對象。耦合度提高,為了解決這個問題,后續(xù)引入Dagger。


          三 MVP的實例(登錄實例)


          下面會根據(jù)這張圖進行分析


          實現(xiàn)步驟:

          • 創(chuàng)建登錄View的接口ILoginView

          • 創(chuàng)建登錄Model的接口ILoginModel

          • 創(chuàng)建LoginActivity作為View的實例,實現(xiàn)ILoginView接口

          • 創(chuàng)建LoginModel作為Model的實例,實現(xiàn)ILoginModel接口

          • 創(chuàng)建LoginPresennter文件

          • 效果圖


          具體實現(xiàn)步驟:


          1.創(chuàng)建登錄View的接口ILoginView

          package showly.com.mytest.view;
                  publicinterfaceILoginView{        /*         * 登錄時view需要知道是否登錄成功后,更新ui         * */ publicvoid isLoginSuccess(boolean success);
          }


          2.創(chuàng)建登錄Model的接口ILoginModel

          package showly.com.mytest.model;
                  publicinterfaceILoginModel{ /* * 需要判斷用戶輸入的賬號與密碼是否正確 * */        publicboolean login(String userName,String password); }


          3.創(chuàng)建LoginActivity作為View的實例,實現(xiàn)ILoginView接口

          publicclassLoginActivityextendsAppCompatActivityimplementsILoginView{
              privateEditText mEtUserName;    privateEditText mMEtPsw;    privateButton mLoginBtn;    privateTextView mTvLoginSuccess; privateLoginPresenter mLoginPresenter;
              @Override    protectedvoid onCreate(Bundle savedInstanceState){        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        initView();        initListener(); }
              privatevoid initListener(){        mLoginPresenter =newLoginPresenter(); mLoginPresenter.setLoginView(this);//將View傳遞給Presenter層
                  mLoginBtn.setOnClickListener(newView.OnClickListener(){            @Override            publicvoid onClick(View view){                //根據(jù)用戶輸入的賬號 密碼進行登錄判斷                String userName = mEtUserName.getText().toString();                String psw = mMEtPsw.getText().toString();                mLoginPresenter.login(userName, psw);            }        }); }
              privatevoid initView(){        mEtUserName =(EditText) findViewById(R.id.et_userName);        mMEtPsw =(EditText) findViewById(R.id.et_psw);        mLoginBtn =(Button) findViewById(R.id.btn_login);        mTvLoginSuccess =(TextView) findViewById(R.id.tv_success);    }
              @Override    publicvoid isLoginSuccess(boolean success){        //更新UI        if(success){            mTvLoginSuccess.setText("登錄成功");            mTvLoginSuccess.setTextColor(Color.BLUE);        }else{            mTvLoginSuccess.setText("登錄失敗");            mTvLoginSuccess.setTextColor(Color.RED);        }    }}


          4.創(chuàng)建LoginModel作為Model的實例,實現(xiàn)ILoginModel接口

          package showly.com.mytest.model;
          public class LoginModel implements ILoginModel{    @Override    publicboolean login(String userName,String password){        /*        * 在這里可以請求服務(wù)器或者數(shù)據(jù)庫中的數(shù)據(jù)        * 請求數(shù)據(jù)省略,假設(shè)請求回來的數(shù)據(jù)為name:showly password:123456        * */        if(userName.equals("showly")){            if(password.equals("123456")){                returntrue;            }        }        returnfalse;    }}


          5.創(chuàng)建LoginPresennter文件

          publicclassLoginPresenter{
              /*    * presenter需要持有view與model接口的引用    * */    privateILoginView mILoginView; privateILoginModel mILoginModel;
              //View層中持有presenter的引用,所以可以創(chuàng)建方法從View中傳遞過來    publicvoid setLoginView(ILoginView loginView){        this.mILoginView = loginView;    }
              //Model層中不持有presenter的引用,所以LoginPresenter構(gòu)建方法中新建對象    publicLoginPresenter(){        //創(chuàng)建Model對象        mILoginModel =newLoginModel(); }     //presenter持有View與Model,創(chuàng)建方法作為兩者的中間站    publicvoid login(String name,String psw){        //將用戶輸入的用戶名 密碼傳遞到Model層進行判斷        boolean isSuccess = mILoginModel.login(name, psw);        //將Model層對比數(shù)據(jù)后的結(jié)果返回        mILoginView.isLoginSuccess(isSuccess);    }}


          6.效果圖


          四 開閉原則介紹

          在這里介紹一下開閉原則,我們在MVP的實例中看到,我們的View和Model是用接口的形式與Presenter進行關(guān)聯(lián),有沒想過這是為什么呢?

          這就涉及到開閉原則了,也就是對擴展進行開放,對修改進行關(guān)閉。

          舉個例子:
          我們定義一個接口:

          publicinterfaceILoginModel{    publicLoginBean getLoginBean();}


          然后創(chuàng)建LoginModel實現(xiàn)這個接口:

          publicclassLoginModelimplementsILoginModel{    @Override    publicLoginBean getLoginBean(){      //假設(shè)這里用原生系統(tǒng)SQLiteOpenHelper      //查詢數(shù)據(jù)庫的代碼    }}


          此時項目經(jīng)理說用原生的數(shù)據(jù)庫查詢不好,需要換GreenDao進行查詢,這個時候我們就需要對getLoginBean方法進行修改,而項目中其它很多地方已經(jīng)使用了該方法,那我們要怎樣才能降低修改的成本呢?


          其實我們剛開始設(shè)計的時候,就應(yīng)該考慮到這個問題,根據(jù)開閉原則,我們可以讓其它地方使用以下的方法進行調(diào)用:

          publicvoid getData(ILoginModel  loginModel){      loginModel.getLoginBean();  }


          這樣需要修改的時候,我們可以對修改進行關(guān)閉,也就是不修改LoginModel,而是新創(chuàng)建GreenDaoModel,這樣就能降低修改的成本。


          需要源碼的童鞋在公眾號【龍旋】對話框輸入【MVPDemo】即可獲取哦.

          瀏覽 49
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  青青草自拍| 中日韩欧美在线 | 国产极品久久7777777 | 日韩一区二区三区无码视频 | 国产99久久久精品无码 |