(1)MVVM初見

MVVM架構(gòu)模式已經(jīng)非称耄火了戈二,我還是只知其一不知其二,搜了很多帖子學(xué)習(xí),這里整理一下學(xué)習(xí)筆記袁梗。

a.便于理解宜鸯,先把一些字面意思放在這里:
Model 模型(數(shù)據(jù)層)

是應(yīng)用程序中處理程序數(shù)據(jù)邏輯的部分,通常負(fù)責(zé)從本地?cái)?shù)據(jù)庫存取遮怜,遠(yuǎn)程存取數(shù)據(jù)淋袖。

View 視圖(UI顯示)

是應(yīng)用程序中處理數(shù)據(jù)顯示的部分,通常視圖都是依據(jù)模型來創(chuàng)建的锯梁。

Controller 控制者即碗,管理者,調(diào)度員

在應(yīng)用程序中處理用戶交互的部分陌凳,通嘲粒控制器負(fù)責(zé)從視圖讀取數(shù)據(jù),控制用戶輸入合敦,并向模型發(fā)送數(shù)據(jù)初橘。

Presenter 主持人
ViewModel 視圖模型
Repository 倉庫,存放處
1.MVC

MVC的模式優(yōu)點(diǎn)在于分離UI與業(yè)務(wù)職責(zé)充岛,增加可測試性與可擴(kuò)展性壁却,但缺點(diǎn)是,View即依賴于Controller又依賴于Model,在修改UI內(nèi)容時裸准,也需要修改對應(yīng)的Model,降低架構(gòu)的靈活性展东,View和Model的職責(zé)存在部分重疊,耦合度高炒俱,實(shí)際操作中很難按照MVC模式嚴(yán)格去分離盐肃。

2.MVP

Model-View-Presenter ;MVP 是從經(jīng)典的模式MVC演變而來权悟,它們的基本思想有相通的地方Controller/Presenter負(fù)責(zé)邏輯的處理砸王,Model提供數(shù)據(jù),View負(fù)責(zé)顯示峦阁。
MVP模式的優(yōu)點(diǎn)是模型與視圖完全分離谦铃,我們可以修改視圖而不影響模型,因?yàn)樵谶@個模式下榔昔,所有的交互都發(fā)生在Presenter內(nèi)部驹闰,也利于脫離用戶接口來測試業(yè)務(wù)邏輯。缺點(diǎn)是會導(dǎo)致視圖和Presenter的交互過于頻分撒会,Presenter與具體的View沒有直接關(guān)聯(lián)嘹朗,而是通過定義好的接口進(jìn)行交互,這會導(dǎo)致有大量的接口生成诵肛,造成代碼繁具屹培,很難維護(hù),這也是很多像我一樣從入坑到放棄這種模式的原因。

3.MVVM

MVP的特質(zhì)是“依賴倒置”褪秀,MVVM的特質(zhì)是“數(shù)據(jù)驅(qū)動”蓄诽。
學(xué)這個的目的,是因?yàn)檫@句話媒吗,顯然說明二者并沒有誰演化自誰的關(guān)系了若专,JetPack MVVM是MVVM模式在Android開發(fā)中的具體落實(shí),“數(shù)據(jù)驅(qū)動”這個理解有點(diǎn)難蝴猪,看帖子不理解就找個教程寫個Demo理解一下,B站是個學(xué)習(xí)網(wǎng)站膊爪,很多優(yōu)質(zhì)UP主提供了幫助自阱,這里貼一下一個小Demo:


籃球比賽計(jì)分器

一個計(jì)分器,點(diǎn)擊加分向?qū)?yīng)的隊(duì)加相應(yīng)的分?jǐn)?shù)米酬,點(diǎn)擊回退取消上一步的操作沛豌,點(diǎn)擊重置將兩隊(duì)的比分清零。
首先定義MyViewModel,繼承自ViewModel,在這里我們定義數(shù)據(jù)赃额,并處理邏輯加派。

public class MyViewModel extends ViewModel {
    // 定義兩隊(duì)的分?jǐn)?shù)
    // MutableLiveData可修改的LiveData,因?yàn)榉謹(jǐn)?shù)需要變化跳芳,LiveData
    private MutableLiveData<Integer> aTeamScore;
    private MutableLiveData<Integer> bTeamScore;
    //緩存兩隊(duì)當(dāng)前分?jǐn)?shù)芍锦,用于回退一步
    private int aBack, bBack;

    public MutableLiveData<Integer> getATeamScore() {
        if (aTeamScore == null) {
            aTeamScore = new MutableLiveData<>();
            aTeamScore.setValue(0);
        }
        return aTeamScore;
    }

    public MutableLiveData<Integer> getBTeamScore() {
        if (bTeamScore == null) {
            bTeamScore = new MutableLiveData<>();
            bTeamScore.setValue(0);
        }
        return bTeamScore;
    }

    /**
     * 給A隊(duì)加分,在添加之前保留A飞盆、B兩隊(duì)的分?jǐn)?shù)娄琉,用于在執(zhí)行undo操作時使用
     * @param p 要加的分?jǐn)?shù)
     */
    public void aTeamAdd(int p) {
        aBack = aTeamScore.getValue();
        bBack = bTeamScore.getValue();
        aTeamScore.setValue(aTeamScore.getValue() + p);
    }

    public void bTeamAdd(int p) {
        aBack = aTeamScore.getValue();
        bBack = bTeamScore.getValue();
        bTeamScore.setValue(bTeamScore.getValue() + p);
    }

    /**
     * 清零
     */
    public void reset() {
        aBack = aTeamScore.getValue();
        bBack = bTeamScore.getValue();
        aTeamScore.setValue(0);
        bTeamScore.setValue(0);
    }

    public void undo() {
        aTeamScore.setValue(aBack);
        bTeamScore.setValue(bBack);
    }
}

布局文件的內(nèi)容除了常規(guī)控件的內(nèi)容,也就是使用了JetPack提供的DataBinding吓歇,篇幅有限這里僅僅對新生事物粘貼一下:

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <data>

        <variable
            name="data"
            type="com.nxhope.community.state.MyViewModel" />
    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".ui.BasketballScoring">

      <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="8dp"
            android:layout_marginTop="8dp"
            android:layout_marginEnd="8dp"
            android:layout_marginBottom="8dp"
            android:text="@{String.valueOf(data.getATeamScore())}"
            android:textColor="#E91E63"
            android:textSize="80sp"
            app:layout_constraintBottom_toTopOf="@+id/guideline10"
            app:layout_constraintEnd_toStartOf="@+id/guideline7"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="@+id/guideline9"
            tools:text="120" />

     <Button
            style="@style/button_one"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="8dp"
            android:layout_marginTop="8dp"
            android:layout_marginEnd="8dp"
            android:layout_marginBottom="8dp"
            android:onClick="@{()->data.aTeamAdd(1)}"
            android:text="+1"
            app:layout_constraintBottom_toTopOf="@+id/guideline11"
            app:layout_constraintEnd_toStartOf="@+id/guideline7"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="@+id/guideline10" />

    <ImageButton
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="60dp"
            android:layout_marginTop="8dp"
            android:layout_marginEnd="8dp"
            android:layout_marginBottom="8dp"
            android:onClick="@{()->data.undo()}"
            app:layout_constraintBottom_toTopOf="@+id/guideline14"
            app:layout_constraintEnd_toStartOf="@+id/guideline7"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="@+id/guideline13"
            app:srcCompat="@drawable/ic_baseline_undo_24" />

   </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

布局文件轉(zhuǎn)換為data-bingding layout這步可以不用手寫孽水,windows用戶選中布局的根節(jié)點(diǎn)alt+enter就會提示出一個選項(xiàng)“convert to data binding layout" 的內(nèi)容, 轉(zhuǎn)換后會多出來<data>節(jié)點(diǎn)中的內(nèi)容城看,我們只需要name中命名女气,在type中導(dǎo)入我們定義好的ViewModel即可。

剩下的事情就是為控件綁定ViewModel提供的數(shù)據(jù)或者操作了测柠,TextView中
android:text="@{String.valueOf(data.getATeamScore())}"為A隊(duì)分?jǐn)?shù)顯示區(qū)域綁定數(shù)據(jù)炼鞠,Button中
android:onClick="@{()->data.aTeamAdd(1)}"綁定了為A隊(duì)加1的操作,當(dāng)然加2加3就類似了轰胁,ImageButton綁定了我們在ViewModel中定義的undo()操作簇搅,也就是回退一步∪硗拢可以看到瘩将,到目前為止,我們好像只關(guān)心了布局文件和ViewModel的內(nèi)容,對于頁面Activity反而還沒下手姿现,不像常規(guī)操作肠仪,之所以這樣,是因?yàn)锳ctiviy中真的沒啥可處理了备典,看代碼:

public class BasketballScoring extends AppCompatActivity {
    private MyViewModel viewModel;
    private ActivityBasketballScoringBinding binding;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //DataBinding
        binding = DataBindingUtil.setContentView(this, R.layout.activity_basketball_scoring);
        //ViewModel
        viewModel = new ViewModelProvider(this, new ViewModelProvider.NewInstanceFactory()).get(MyViewModel.class);
        binding.setData(viewModel);
        binding.setLifecycleOwner(this);
    }
}

Activity中我們只是做了將布局和ViewModel綁定异旧,當(dāng)然這里還寫了一些LiveData和Lifecycle的內(nèi)容(我還沒研究透徹,這里按下不表提佣,聽下回分說)吮蛹,不是重點(diǎn),重點(diǎn)是拌屏,Activity中太簡潔了潮针,常見的FindViewById( ),setOnclickListener( ),setText( )統(tǒng)統(tǒng)不見蹤影倚喂,以及我們可能要定義的常量每篷,Bean什么的也沒了,這就很香了端圈。
玩玩這個Demo,比如刪除布局文件中的一些內(nèi)容焦读,常規(guī)方式可能就會出現(xiàn)空指針,控件找不到造成的Crash,但現(xiàn)在不會了舱权,MVVM模式用于解決“視圖調(diào)用一致性問題”這句話也誠不欺我矗晃,這時候再拿出KunMinX大佬的圖:



再品品,想總結(jié)些內(nèi)容宴倍,品出來的是:“我是小白喧兄,特別的白”、
帖子前面提到了Repository 啊楚,這里面并沒有說吠冤,本著的是不懂就不裝懂的原則,況且程序員有的東西懂了怎么用恭理,不一定會表達(dá)拯辙,繼續(xù)學(xué)習(xí),Android推出的JetPack內(nèi)容是時候?qū)W學(xué)了:


Jetpack
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末颜价,一起剝皮案震驚了整個濱河市涯保,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌周伦,老刑警劉巖夕春,帶你破解...
    沈念sama閱讀 217,907評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異专挪,居然都是意外死亡及志,警方通過查閱死者的電腦和手機(jī)片排,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,987評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來速侈,“玉大人率寡,你說我怎么就攤上這事∫邪幔” “怎么了冶共?”我有些...
    開封第一講書人閱讀 164,298評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長每界。 經(jīng)常有香客問我捅僵,道長,這世上最難降的妖魔是什么眨层? 我笑而不...
    開封第一講書人閱讀 58,586評論 1 293
  • 正文 為了忘掉前任庙楚,我火速辦了婚禮,結(jié)果婚禮上谐岁,老公的妹妹穿的比我還像新娘。我一直安慰自己榛臼,他們只是感情好伊佃,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,633評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著沛善,像睡著了一般航揉。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上金刁,一...
    開封第一講書人閱讀 51,488評論 1 302
  • 那天帅涂,我揣著相機(jī)與錄音,去河邊找鬼尤蛮。 笑死媳友,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的产捞。 我是一名探鬼主播醇锚,決...
    沈念sama閱讀 40,275評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼坯临!你這毒婦竟也來了焊唬?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,176評論 0 276
  • 序言:老撾萬榮一對情侶失蹤看靠,失蹤者是張志新(化名)和其女友劉穎赶促,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體挟炬,經(jīng)...
    沈念sama閱讀 45,619評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡鸥滨,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,819評論 3 336
  • 正文 我和宋清朗相戀三年嗦哆,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片爵赵。...
    茶點(diǎn)故事閱讀 39,932評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡吝秕,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出空幻,到底是詐尸還是另有隱情烁峭,我是刑警寧澤,帶...
    沈念sama閱讀 35,655評論 5 346
  • 正文 年R本政府宣布秕铛,位于F島的核電站约郁,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏但两。R本人自食惡果不足惜鬓梅,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,265評論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望谨湘。 院中可真熱鬧绽快,春花似錦、人聲如沸紧阔。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,871評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽擅耽。三九已至活孩,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間乖仇,已是汗流浹背憾儒。 一陣腳步聲響...
    開封第一講書人閱讀 32,994評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留乃沙,地道東北人起趾。 一個月前我還...
    沈念sama閱讀 48,095評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像警儒,于是被迫代替她去往敵國和親阳掐。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,884評論 2 354