《安卓-深入淺出MVVM教程》原理篇-01 MyLiveData(最簡單的LiveData)

簡介

背景

這幾年 MVP 架構(gòu)在安卓界非常流行媒吗,幾乎已經(jīng)成為主流框架念搬,它讓業(yè)務(wù)邏輯 和 UI操作相對獨(dú)立瓷产,使得代碼結(jié)構(gòu)更清晰。


MVVM 在前端火得一塌糊涂吱窝,而在安卓這邊卻基本沒見到幾個人在用讥邻,看到介紹 MVVM 也最多是講 DataBinding 或 介紹思想的迫靖。偶爾看到幾篇提到應(yīng)用的院峡,還是對谷歌官網(wǎng)的Architecture Components 文章的翻譯。

相信大家看別人博客或官方文檔的時候系宜,總會碰到一些坑照激。要么入門教程寫得太復(fù)雜(無力吐槽,前面寫一堆原理盹牧,各種高大上的圖俩垃,然并卵,到實(shí)踐部分一筆帶過汰寓,你確定真的是入門教程嗎)口柳。要么就是簡單得就是一個 hello world,然后就沒有下文了(看了想罵人)有滑。


實(shí)在看不下去的我跃闹,決定插手你的人生。

目錄

《安卓-深入淺出MVVM教程》大致分兩部分:應(yīng)用篇、原理篇望艺。
采用循序漸進(jìn)方式苛秕,內(nèi)容深入淺出,符合人類學(xué)習(xí)規(guī)律找默,希望大家用最少時間掌握 MVVM艇劫。

應(yīng)用篇:

01 Hello MVVM (快速入門)
02 Repository (數(shù)據(jù)倉庫)
03 Cache (本地緩存)
04 State Lcee (加載/空/錯誤/內(nèi)容視圖)
05 Simple Data Source (簡單的數(shù)據(jù)源)
06 Load More (加載更多)
07 DataBinding (數(shù)據(jù)與視圖綁定)
08 RxJava2
09 Dragger2
10 Abstract (抽象)
11 Demo (例子)
12-n 待定(歡迎 github 提建議)

原理篇

01 MyLiveData(最簡單的LiveData)
02-n 待定(并不是解讀源碼,那樣太無聊了惩激,打算帶你從0擼一個 Architecture)

關(guān)于提問

本人水平和精力有限店煞,如果有大佬發(fā)現(xiàn)哪里寫錯了或有好的建議,歡迎在本教程附帶的 github倉庫 提issue风钻。
What浅缸?為什么不在博客留言?考慮到國內(nèi)轉(zhuǎn)載基本無視版權(quán)的情況魄咕,一般來說你都不是在源出處看到這篇文章衩椒,所以留言我也一般是看不到的。

教程附帶代碼

https://github.com/ittianyu/MVVM

應(yīng)用篇放在 app 模塊下哮兰,原理篇放在 implementation 模塊下毛萌。
每一節(jié)代碼采用不同包名,相互獨(dú)立喝滞。

前言

上一篇阁将,介紹了 MVVM 的常見用法。
這一篇將會從零開始構(gòu)建 MVVM 的基礎(chǔ)類庫右遭。

怎么實(shí)現(xiàn) View 和 ViewModel 的綁定做盅?

拋開上一篇講得內(nèi)容,現(xiàn)在問題如上窘哈,你會怎么設(shè)計(jì)吹榴?
降低難度,假設(shè)我們先不考慮生命周期和其他因素滚婉,究竟怎么樣才能實(shí)現(xiàn) ViewModel改變時通知view图筹,view操作時通知ViewModel?

通過展開問題让腹,發(fā)現(xiàn)可以轉(zhuǎn)化為兩個問題远剩,采用分治思想

view操作時通知ViewModel

這個很簡單,和我們平時做開發(fā)時一樣的思路骇窍,添加 UI 事件監(jiān)聽瓜晤,觸發(fā)之后,主動去調(diào)用 ViewModel腹纳。(可能這思想不太準(zhǔn)確痢掠,簡單起見哈恰,先這樣理解吧,后面再糾正)

ViewModel改變時通知view

那這個呢志群?難道是數(shù)據(jù)獲取成功時着绷,去調(diào)用 View?
那這就又回到之前MVP MVC 的思路了锌云。
MVVM 的優(yōu)點(diǎn)是荠医,數(shù)據(jù)改動,自動反映到 View 上桑涎。也就是說彬向,不需要我們主動去操作 View。
既然主動不好攻冷,那就被動吧娃胆。(手動滑稽)

換句話說,是 View 主動去監(jiān)聽數(shù)據(jù)變化等曼,View 自己決定怎么響應(yīng)里烦,而不是被 ViewModle 推著走。

那答案就很明顯了禁谦,觀察者模式胁黑。

實(shí)現(xiàn)

雖然思路知道了,但該從哪里開始寫 LiveData 呢州泊?
最快的辦法是需要什么寫什么丧蘸。

需求

所以這里快速寫一個簡單的案例:
界面中只有一個 TextView,點(diǎn)擊屏幕給 TextView 隨機(jī)設(shè)置一個0-1000的數(shù)字遥皂。

xml

請?jiān)试S我用 2 秒寫完這個界面

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/v_root"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:orientation="vertical">

    <TextView
        android:id="@+id/tv_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="name" />
</LinearLayout>

MyLiveDataActivity

參照上一篇的用法力喷,很容易寫出這樣的代碼。
和之前比演训,這里直接使用 LiveData弟孟,并且省略了 lifecycle 的傳入。也就是調(diào)用 ldName.observer 來監(jiān)聽數(shù)據(jù)的變化仇祭,記得在 onDestroy 時取消監(jiān)聽披蕉。

public class MyLiveDataActivity extends AppCompatActivity {

    private MyLiveData<String> ldName;
    private TextView tvName;
    private View vRoot;
    private OnValueChangeListener<String> nameObserver;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        initView();
        initData();
        initEvent();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();

        ldName.unobserver(nameObserver);
    }

    private void initView() {
        setContentView(R.layout.a_my_livedata);
        tvName = (TextView) findViewById(R.id.tv_name);
        vRoot = findViewById(R.id.v_root);
    }

    private void initData() {
        ldName = new MyLiveData<>();
        nameObserver = new OnValueChangeListener<String>() {
            @Override
            public void onChange(String value) {
                tvName.setText(value);
            }
        };
        ldName.observer(nameObserver);
    }

    private void initEvent() {
        vRoot.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                resetValue();
            }
        });
    }

    private void resetValue() {
        int randomInt = (int) (Math.random() * 1000);
        ldName.setValue(randomInt + "");
    }
}

MyLiveData 定義

這個時候代碼肯定是報錯的,上面是先用后實(shí)現(xiàn)乌奇,這樣就明確了 MyLiveData 公開的方法和功能。寫起來就很清晰了眯娱。

通過用法礁苗,我們就能定義出一個接口和一個類,目前都是空實(shí)現(xiàn)徙缴。

public interface OnValueChangeListener<T> {
    void onChange(T value);
}

public class MyLiveData<T> {

    public void observer(OnValueChangeListener<T> observer) {

    }

    public void unobserver(OnValueChangeListener<T> observer) {
        
    }

    public void setValue(T value) {

    }
}

MyLiveData 實(shí)現(xiàn)

最簡單的觀察者模式试伙,就是用個容器把監(jiān)聽器存起來嘁信,當(dāng)數(shù)據(jù)改變時,去調(diào)用監(jiān)聽器疏叨。

public class MyLiveData<T> {
    private List<OnValueChangeListener<T>> observers = new ArrayList<>();

    public void observer(OnValueChangeListener<T> observer) {
        observers.add(observer);
    }

    public void setValue(T value) {
        for (OnValueChangeListener<T> listener :observers) {
            listener.onChange(value);
        }
    }

    public void unobserver(OnValueChangeListener<T> observer) {
        observers.remove(observer);
    }
}

總結(jié)

LiveData 就這么簡單潘靖?
當(dāng)然不是,我們現(xiàn)在寫的 LiveData 還需要手動取消監(jiān)聽蚤蔓。
而谷歌的 LiveData 卻不用卦溢。

所以下一步的目標(biāo)是逐步完善它。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末秀又,一起剝皮案震驚了整個濱河市单寂,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌吐辙,老刑警劉巖宣决,帶你破解...
    沈念sama閱讀 218,941評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異昏苏,居然都是意外死亡尊沸,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評論 3 395
  • 文/潘曉璐 我一進(jìn)店門贤惯,熙熙樓的掌柜王于貴愁眉苦臉地迎上來椒丧,“玉大人,你說我怎么就攤上這事救巷『” “怎么了?”我有些...
    開封第一講書人閱讀 165,345評論 0 356
  • 文/不壞的土叔 我叫張陵浦译,是天一觀的道長棒假。 經(jīng)常有香客問我,道長精盅,這世上最難降的妖魔是什么帽哑? 我笑而不...
    開封第一講書人閱讀 58,851評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮叹俏,結(jié)果婚禮上妻枕,老公的妹妹穿的比我還像新娘。我一直安慰自己粘驰,他們只是感情好屡谐,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,868評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著蝌数,像睡著了一般愕掏。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上顶伞,一...
    開封第一講書人閱讀 51,688評論 1 305
  • 那天饵撑,我揣著相機(jī)與錄音剑梳,去河邊找鬼。 笑死滑潘,一個胖子當(dāng)著我的面吹牛垢乙,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播语卤,決...
    沈念sama閱讀 40,414評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼追逮,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了粱侣?” 一聲冷哼從身側(cè)響起羊壹,我...
    開封第一講書人閱讀 39,319評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎齐婴,沒想到半個月后油猫,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,775評論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡柠偶,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年情妖,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片诱担。...
    茶點(diǎn)故事閱讀 40,096評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡毡证,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出蔫仙,到底是詐尸還是另有隱情料睛,我是刑警寧澤,帶...
    沈念sama閱讀 35,789評論 5 346
  • 正文 年R本政府宣布摇邦,位于F島的核電站恤煞,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏施籍。R本人自食惡果不足惜居扒,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,437評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望丑慎。 院中可真熱鬧喜喂,春花似錦、人聲如沸竿裂。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽铛绰。三九已至诈茧,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間捂掰,已是汗流浹背敢会。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評論 1 271
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留这嚣,地道東北人鸥昏。 一個月前我還...
    沈念sama閱讀 48,308評論 3 372
  • 正文 我出身青樓,卻偏偏與公主長得像姐帚,于是被迫代替她去往敵國和親吏垮。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,037評論 2 355

推薦閱讀更多精彩內(nèi)容