<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>

          十分鐘上手MVC、MVP、MVVM

          共 11143字,需瀏覽 23分鐘

           ·

          2020-12-17 09:58





          導(dǎo)讀



          關(guān)于MVC、MVP、MVVM的具體概念和優(yōu)缺點網(wǎng)上有很多文章講解,這里不再贅述。

          但是對于一個沒有實戰(zhàn)過這三種架構(gòu)模式的同學(xué)們,當(dāng)你辛辛苦苦花了幾個小時讀了關(guān)于這三種模式的文章,看了一些彼此分離沒有對比性的示例代碼。你們真的會很快上手這三種架構(gòu)模式的寫法嗎?

          本文通過一個三合一demo,關(guān)鍵點代碼進(jìn)行注釋,十分鐘帶你入門。讓你分分鐘看懂三種模式的區(qū)別,快速上手三種寫法。

          這是一個點擊按鈕,模擬耗時任務(wù)獲取數(shù)據(jù),然后設(shè)置Textview的demo。對,就是這么簡單,方便大家入門。



          01

          MVC


          對于MVC模式,本demo只有兩個類:MvcMainActivity和GreetingGeneratorModel。

          在MVC模式中,Activity就是Controller,同時也是View的一部分,它會調(diào)用Model層進(jìn)行數(shù)據(jù)獲取。Model層,封裝各種數(shù)據(jù)來源,和View層是直接通信的,它會調(diào)用View層里的更新View方法。


           1//?Activity即是Controller,同時也是View的一部分
          2public?class?MvcMainActivity?extends?AppCompatActivity?{
          3????TextView?greetingTextView;
          4????Button?helloButton;
          5????Button?goodbyeButtonClicked;
          6
          7????@Override
          8????protected?void?onCreate(Bundle?savedInstanceState)?{
          9????????super.onCreate(savedInstanceState);
          10????????setContentView(R.layout.activity_mvcmain);
          11????????greetingTextView?=?findViewById(R.id.greetingTextView);
          12????????helloButton?=?findViewById(R.id.helloButton);
          13????????goodbyeButtonClicked?=?findViewById(R.id.goodbyeButtonClicked);
          14????????//?(1)View傳遞調(diào)用到Controller
          15????????helloButton.setOnClickListener(new?View.OnClickListener()?{
          16????????????@Override
          17????????????public?void?onClick(View?view)?{
          18????????????????//?(2)Controller直接調(diào)用Model層
          19????????????????new?GreetingGeneratorModel("HelloWorld",?greetingTextView).execute();
          20????????????}
          21????????});
          22????????//?(1)View傳遞調(diào)用到Controller
          23????????goodbyeButtonClicked.setOnClickListener(new?View.OnClickListener()?{
          24????????????@Override
          25????????????public?void?onClick(View?view)?{
          26????????????????//?(2)Controller直接調(diào)用Model層
          27????????????????new?GreetingGeneratorModel("GoodBye",?greetingTextView).execute();
          28????????????}
          29????????});
          30????}
          31}


           1//?Model層,封裝各種數(shù)據(jù)來源,和View層是直接通信的
          2public?class?GreetingGeneratorModel?extends?AsyncTask<Void,?Void,?Integer>?{
          3????private?String?baseText;
          4????private?TextView?greetingTextView;
          5
          6????public?GreetingGeneratorModel(String?baseText,?TextView?greetingTextView)?{
          7????????this.baseText?=?baseText;
          8????????this.greetingTextView?=?greetingTextView;
          9????}
          10
          11????//?Simulates?computing?and?returns?a?random?integer
          12????@Override
          13????protected?Integer?doInBackground(Void...?params)?{
          14????????try?{
          15????????????//?Simulate?computing
          16????????????Thread.sleep(2000);
          17????????}?catch?(InterruptedException?e)?{
          18????????}
          19????????return?(int)?(Math.random()?*?100);
          20????}
          21
          22????@Override
          23????protected?void?onPostExecute(Integer?randomInt)?{
          24????????//?(3)Model層調(diào)用View
          25????????if?("HelloWorld".equals(baseText))?{
          26????????????greetingTextView.setTextColor(Color.RED);
          27????????}?else?{
          28????????????greetingTextView.setTextColor(Color.BLUE);
          29????????}
          30????????greetingTextView.setText(baseText?+?randomInt);
          31????}
          32}


          好啦。MVC模式講完啦,就是這么簡單,這也是大家初學(xué)Android時最常見的寫法。


          02

          MVP



          在實現(xiàn)MVP模式寫法時,我們借助了Mosby這個開源庫。通過Mosby我們可以很輕松地實現(xiàn)MVP的寫法。

          對于MVP模式,本demo有四個類:除了有MvpMainActivity和GreetingGeneratorModel外,新增了HelloWorldView和HelloWorldPresenter。


          可以看到,相比于MVC模式,首先,HelloWorldView定義了操作View的接口。


          1//?Mvp?View?接口,定義對View的操作接口
          2public?interface?HelloWorldView?extends?MvpView?{
          3????void?showHello(String?greetingText);
          4
          5????void?showGoodbye(String?greetingText);
          6}


          MvpMainActivity一方面要調(diào)用HelloWorldPresenter層進(jìn)行數(shù)據(jù)操作;另一方面要實現(xiàn)HelloWorldView中具體操作View的接口。


           1//?View層,視圖層
          2public?class?MvpMainActivity?extends?MvpActivity<HelloWorldView,?HelloWorldPresenter>?implements?HelloWorldView?{
          3????TextView?greetingTextView;
          4????Button?helloButton;
          5????Button?goodbyeButtonClicked;
          6
          7????@Override
          8????protected?void?onCreate(Bundle?savedInstanceState)?{
          9????????super.onCreate(savedInstanceState);
          10????????setContentView(R.layout.activity_mvpmain);
          11????????greetingTextView?=?findViewById(R.id.greetingTextView);
          12????????helloButton?=?findViewById(R.id.helloButton);
          13????????goodbyeButtonClicked?=?findViewById(R.id.goodbyeButtonClicked);
          14????????helloButton.setOnClickListener(new?View.OnClickListener()?{
          15????????????@Override
          16????????????public?void?onClick(View?view)?{
          17????????????????//?(1)調(diào)用Presenter層數(shù)據(jù)操作
          18????????????????presenter.greetHello();
          19????????????}
          20????????});
          21????????goodbyeButtonClicked.setOnClickListener(new?View.OnClickListener()?{
          22????????????@Override
          23????????????public?void?onClick(View?view)?{
          24????????????????//?(1)調(diào)用Presenter層數(shù)據(jù)操作
          25????????????????presenter.greetGoodbye();
          26????????????}
          27????????});
          28????}
          29
          30????@Override
          31????protected?void?onDestroy()?{
          32????????super.onDestroy();
          33????}
          34
          35????@NonNull
          36????@Override
          37????public?HelloWorldPresenter?createPresenter()?{
          38????????return?new?HelloWorldPresenter();
          39????}
          40
          41????//?實現(xiàn)Mvp?View?接口,具體對View的操作
          42????@Override
          43????public?void?showHello(String?greetingText)?{
          44????????greetingTextView.setTextColor(Color.RED);
          45????????greetingTextView.setText(greetingText);
          46????}
          47
          48????//?實現(xiàn)Mvp?View?接口,具體對View的操作
          49????@Override
          50????public?void?showGoodbye(String?greetingText)?{
          51????????greetingTextView.setTextColor(Color.BLUE);
          52????????greetingTextView.setText(greetingText);
          53????}
          54}


          GreetingGeneratorModel仍舊提供各種數(shù)據(jù)來源,但是要定義回調(diào)監(jiān)聽,對Presenter提供接口。


           1//?Model層,封裝各種數(shù)據(jù)來源,對Prestener層提供接口
          2public?class?GreetingGeneratorModel?extends?AsyncTask<Void,?Void,?Integer>?{
          3????//?異步任務(wù)中要定義回調(diào)監(jiān)聽
          4????public?interface?GreetingTaskListener?{
          5????????public?void?onGreetingGenerated(String?greetingText);
          6????}
          7
          8????private?String?baseText;
          9????private?GreetingTaskListener?listener;
          10
          11????public?GreetingGeneratorModel(String?baseText,?GreetingTaskListener?listener)?{
          12????????this.baseText?=?baseText;
          13????????this.listener?=?listener;
          14????}
          15
          16????//?Simulates?computing?and?returns?a?random?integer
          17????@Override
          18????protected?Integer?doInBackground(Void...?params)?{
          19????????try?{
          20????????????//?Simulate?computing
          21????????????Thread.sleep(2000);
          22????????}?catch?(InterruptedException?e)?{
          23????????}
          24????????return?(int)?(Math.random()?*?100);
          25????}
          26
          27????@Override
          28????protected?void?onPostExecute(Integer?randomInt)?{
          29????????//?(3)執(zhí)行回調(diào)關(guān)聯(lián)到Presenter層
          30????????listener.onGreetingGenerated(baseText?+?"?"?+?randomInt);
          31????}
          32}


          HelloWorldPresenter既要調(diào)用Model層進(jìn)行數(shù)據(jù)獲取,也要實現(xiàn)GreetingGeneratorModel層的回調(diào)監(jiān)聽操作View層更新View。


           1//?Presenter層,邏輯控制層
          2public?class?HelloWorldPresenter?extends?MvpBasePresenter<HelloWorldView>?{
          3????//?Greeting?Task?is?"business?logic"
          4????private?GreetingGeneratorModel?greetingTask;
          5
          6????private?void?cancelGreetingTaskIfRunning()?{
          7????????if?(greetingTask?!=?null)?{
          8????????????greetingTask.cancel(true);
          9????????}
          10????}
          11
          12????public?void?greetHello()?{
          13????????cancelGreetingTaskIfRunning();
          14????????//?實現(xiàn)Model層的回調(diào)監(jiān)聽
          15????????greetingTask?=?new?GreetingGeneratorModel("HelloWorld",?new?GreetingGeneratorModel.GreetingTaskListener()?{
          16????????????@Override
          17????????????public?void?onGreetingGenerated(String?greetingText)?{
          18????????????????//?(4)調(diào)用View層更新View
          19????????????????if?(isViewAttached())
          20????????????????????getView().showHello(greetingText);
          21????????????}
          22????????});
          23????????//?(2)調(diào)用Model層獲取數(shù)據(jù)
          24????????greetingTask.execute();
          25????}
          26
          27????public?void?greetGoodbye()?{
          28????????cancelGreetingTaskIfRunning();
          29????????//?實現(xiàn)Model層的回調(diào)監(jiān)聽
          30????????greetingTask?=?new?GreetingGeneratorModel("Goodbye",?new?GreetingGeneratorModel.GreetingTaskListener()?{
          31????????????public?void?onGreetingGenerated(String?greetingText)?{
          32????????????????//?(4)調(diào)用View層更新View
          33????????????????if?(isViewAttached())
          34????????????????????getView().showGoodbye(greetingText);
          35????????????}
          36????????});
          37????????//?(2)調(diào)用Model層獲取數(shù)據(jù)
          38????????greetingTask.execute();
          39????}
          40
          41????//?Called?when?Activity?gets?destroyed,?so?cancel?running?background?task
          42????public?void?detachView(boolean?retainPresenterInstance)?{
          43????????super.detachView(retainPresenterInstance);
          44????????if?(!retainPresenterInstance)?{
          45????????????cancelGreetingTaskIfRunning();
          46????????}
          47????}
          48}



          03

          MVVM


          要使用MVVM模式,首先你需要在app下的buld.gradle中添加DataBinding框架配置:


          1????//?DataBinding配置
          2????dataBinding?{
          3????????enabled?=?true
          4????}


          然后對布局文件作出一定調(diào)整:根標(biāo)簽是layout,根標(biāo)簽之下增加了一個data標(biāo)簽,它包含兩個variable標(biāo)簽。

          對于原先的Button按鈕通過@{handlers.onClickHello}進(jìn)行事件綁定前置操作。對于原先的Textview通過@{greetingGeneratorObj.baseText} 進(jìn)行數(shù)據(jù)綁定前置操作。


           1<layout?xmlns:android="http://schemas.android.com/apk/res/android">
          2
          3????<data>
          4
          5????????<variable
          6????????????name="handlers"
          7????????????type="com.example.architecturalpatterndemo.mvvm.MyHandlers"?/>

          8
          9????????<variable
          10????????????name="greetingGeneratorObj"
          11????????????type="com.example.architecturalpatterndemo.mvvm.GreetingGeneratorObj"?/>

          12????data>
          13
          14????<LinearLayout
          15????????android:layout_width="match_parent"
          16????????android:layout_height="match_parent"
          17????????android:orientation="vertical">

          18
          19????????<TextView
          20????????????android:id="@+id/greetingTextView"
          21????????????android:layout_width="wrap_content"
          22????????????android:layout_height="wrap_content"
          23????????????android:text="@{greetingGeneratorObj.baseText}"?/>

          24
          25????????<Button
          26????????????android:id="@+id/helloButton"
          27????????????android:layout_width="wrap_content"
          28????????????android:layout_height="wrap_content"
          29????????????android:onClick="@{handlers.onClickHello}"
          30????????????android:text="hello"?/>

          31
          32????????<Button
          33????????????android:id="@+id/goodbyeButtonClicked"
          34????????????android:layout_width="wrap_content"
          35????????????android:layout_height="wrap_content"
          36????????????android:onClick="@{handlers.onClickGoodbye}"
          37????????????android:text="Good?bye"?/>

          38????LinearLayout>
          39layout>



          在MVVM模式中,本demo有四個類:除了MvvmMainActivity和GreetingGeneratorModel外,新增了GreetingGeneratorObj數(shù)據(jù)對象類和MyHandlers綁定方法類。


          在MvvmMainActivity中,通過ActivityMvvmmainBinding對象的setHandlers方法進(jìn)行事件綁定,可以看到,setOnClickListener代碼消失了;

          通過ActivityMvvmmainBinding對象的setGreetingGeneratorObj方法進(jìn)行數(shù)據(jù)綁定。具體雙向數(shù)據(jù)綁定是怎么執(zhí)行的,都由DataBinding框架來完成。


           1public?class?MvvmMainActivity?extends?AppCompatActivity?{
          2
          3????@Override
          4????protected?void?onCreate(Bundle?savedInstanceState)?{
          5????????super.onCreate(savedInstanceState);
          6????????ActivityMvvmmainBinding?binding?=?DataBindingUtil.setContentView(this,?R.layout.activity_mvvmmain);
          7????????GreetingGeneratorObj?greetingGeneratorObj?=?new?GreetingGeneratorObj("");
          8????????//?(1)按套路寫好數(shù)據(jù)綁定,具體怎么實現(xiàn)雙向數(shù)據(jù)綁定,都由DataBinding框架來完成
          9????????//?數(shù)據(jù)綁定
          10????????binding.setGreetingGeneratorObj(greetingGeneratorObj);
          11????????//?事件綁定
          12????????binding.setHandlers(new?MyHandlers(greetingGeneratorObj));
          13????}
          14
          15}


           1//?Model層,封裝各種數(shù)據(jù)來源
          2public?class?GreetingGeneratorModel?extends?AsyncTask<Void,?Void,?Integer>?{
          3????private?String?baseText;
          4????private?GreetingGeneratorObj?greetingGeneratorObj;
          5
          6????public?GreetingGeneratorModel(String?baseText,?GreetingGeneratorObj?greetingGeneratorObj)?{
          7????????this.baseText?=?baseText;
          8????????this.greetingGeneratorObj?=?greetingGeneratorObj;
          9????}
          10
          11????//?Simulates?computing?and?returns?a?random?integer
          12????@Override
          13????protected?Integer?doInBackground(Void...?params)?{
          14????????try?{
          15????????????//?Simulate?computing
          16????????????Thread.sleep(2000);
          17????????}?catch?(InterruptedException?e)?{
          18????????}
          19
          20????????return?(int)?(Math.random()?*?100);
          21????}
          22
          23????@Override
          24????protected?void?onPostExecute(Integer?randomInt)?{
          25????????//?(3)ViewModel層調(diào)用ViewModel層
          26????????greetingGeneratorObj.setBaseText(baseText?+?randomInt);
          27????}
          28}


          數(shù)據(jù)對象的set方法需要增加notifyPropertyChanged方法。


           1//?數(shù)據(jù)對象類
          2public?class?GreetingGeneratorObj?extends?BaseObservable?{
          3????public?static?String?baseText;
          4
          5????public?GreetingGeneratorObj(String?baseText)?{
          6????????this.baseText?=?baseText;
          7????}
          8
          9????@Bindable
          10????public?String?getBaseText()?{
          11????????return?baseText;
          12????}
          13
          14????public?void?setBaseText(String?baseText)?{
          15????????GreetingGeneratorObj.baseText?=?baseText;
          16????????notifyPropertyChanged(BR.baseText);
          17????}
          18}


          MyHandlers中實現(xiàn)操作Model的方法,這些方法與xml中布局文件是對應(yīng)的,會被DataBinding框架自動調(diào)用。


           1public?class?MyHandlers?{
          2????private?GreetingGeneratorObj?greetingGeneratorObj;
          3
          4????public?MyHandlers(GreetingGeneratorObj?greetingGeneratorObj)?{
          5????????this.greetingGeneratorObj?=?greetingGeneratorObj;
          6????}
          7
          8????public?void?onClickHello(View?view)?{
          9????????//?(2)ViewModel層調(diào)用Model層
          10????????new?GreetingGeneratorModel("HelloWorld",?greetingGeneratorObj).execute();
          11????}
          12
          13????public?void?onClickGoodbye(View?view)?{
          14????????//?(2)ViewModel層調(diào)用Model層
          15????????new?GreetingGeneratorModel("GoodBye",?greetingGeneratorObj).execute();
          16????}
          17}


          04

          demo地址

          以上就是本demo的全部啦。通過關(guān)系圖和關(guān)鍵代碼注釋,使用三種模式實現(xiàn)同樣的小功能,這樣能很清楚地對比。十分鐘上手三種模式的寫法!具體demo地址如下:

          https://github.com/youjinjin/ArchitecturalPatternDemo




          瀏覽 44
          點贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

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

          手機(jī)掃一掃分享

          分享
          舉報
          <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>
                  国产探花免费观看 | 天天做天天干天天做 | 黄色小视频在线看 | 蜜臀视频网站狠狠操b | 日本人日逼视频 |