【Jetpack日記(4)】ViewModel和LiveData的基本介紹

ViewModel介紹

關(guān)于ViewModel分瘾,根據(jù)官網(wǎng)開發(fā)文檔介紹,它可以管理界面控制器(如 Activity 和 Fragment)的生命周期紊婉。Android 框架可能會決定銷毀或重新創(chuàng)建界面控制器药版,以響應(yīng)完全不受您控制的某些用戶操作或設(shè)備事件。意思就是比如當Activity銷毀或者重新創(chuàng)建的時候(比如屏幕選擇)喻犁,因配置更改而重新創(chuàng)建 Activity 后槽片,新 Activity 必須重新提取用戶列表。對于簡單的數(shù)據(jù)肢础,Activity 可以使用onSaveInstanceState()onCreate()進行數(shù)據(jù)恢復(fù)还栓。但是,一些較大的數(shù)據(jù)传轰,就不太適合用通常的方法來進行恢復(fù)了囊陡。而ViewModel就可以幫助我們來解決這個問題敷存。

LiveData介紹

根據(jù)官網(wǎng)開發(fā)文檔說明财松,它是一個可以感知生命周期痴脾,就是和LifeCycle綁定的一個數(shù)據(jù)存儲類,而且LiveData遵照觀察者模式期贫,當生命周期發(fā)生變化的時候跟匆,LiveData就會通知被觀察的那些對象,這樣就可以實現(xiàn)實時更新界面數(shù)據(jù)了通砍,而且在生命周期結(jié)束的時候玛臂,也會自動進行銷毀,因為通過LifeCycle進行綁定了埠帕,這樣也不會發(fā)生內(nèi)存泄露垢揩,也就不需要手動去處理生命周期的那些事件了。

LiveData的優(yōu)勢敛瓷,官網(wǎng)都有說明


ViewModel的基本使用

老樣子,首先導(dǎo)入依賴斑匪,參考官方導(dǎo)入說明呐籽。

其實關(guān)于ViewModel和LiveData的基本使用,其實官網(wǎng)說明的很清楚了蚀瘸,我這里只是基本介紹一下狡蝶,首先是在Activity中使用,我們需要創(chuàng)建一個類來繼承ViewModel贮勃,這里的MutableLiveData其實就是Jetpack的另一個架構(gòu)組件LiveData組件贪惹,具體用法我稍后再說。

public class MyViewModel extends ViewModel {
    
    private MutableLiveData<List<User>> list;

    public LiveData<List<User>> getUsers() {
        if (list == null) {
            list = new MutableLiveData<>();
            loadUsers();
        }

        return list;
    }


    private void loadUsers() {
        // Do an asynchronous operation to fetch users.
        User user = new User();
        user.setName("測試");
        List<User> users = new ArrayList<>();
        users.add(user);
        list.setValue(users);

    }
}


//JavaBean
public class User {


    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

在Activity中寂嘉,我們通過ViewModelProviders來獲取和調(diào)用需要的ViewModel就好了奏瞬,代碼如下:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        final TextView textView;
        textView = findViewById(R.id.test);

        MyViewModel model = ViewModelProviders.of(this).get(MyViewModel.class);
        model.getUsers().observe(this, new Observer<List<User>>() {
            @Override
            public void onChanged(List<User> users) {
                textView.setText(users.get(0).getName());
            }
        });

    }
}

MainActivity運行結(jié)果


Fragment數(shù)據(jù)共享

兩個Activity之間或者Fragment之間傳遞數(shù)據(jù)是很經(jīng)常的事情枫绅,一般傳遞數(shù)據(jù)之間我們不是通過Intent,要不就是通過Bundle來進行數(shù)據(jù)的傳遞硼端,我們其實也可以通過ViewModel來進行數(shù)據(jù)的傳遞并淋,舉個例子,比如在一個Fragment單擊一個控件珍昨,然后進行數(shù)據(jù)傳遞县耽,這個數(shù)據(jù)會顯示在第二個Fragment上面,首先修改一下ViewModel

public class MyViewModel extends ViewModel {

    private MutableLiveData<User> model  = new MutableLiveData<>();




    public void select(User user){
         model.setValue(user);
    }

    public User getSelect(){
        return model.getValue();
    }
}

然后在兩個Fragment中分別設(shè)置和獲取镣典,代碼如下:

private MyViewModel myViewModel;

private void initView(View root) {
    root.findViewById(R.id.text_home).setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            myViewModel  = ViewModelProviders.of(getActivity()).get(MyViewModel.class);
            User user = new User();
            user.setName("傳遞Fragment");
            myViewModel.select(user);
            Toast.makeText(getActivity(),"已點擊",Toast.LENGTH_SHORT).show();
        }
    });
}

然后在要獲取的Fragment中進行獲取就好了兔毙,通過getSelect()方法。

final TextView textView = root.findViewById(R.id.text_dashboard);
myViewModel = ViewModelProviders.of(getActivity()).get(MyViewModel.class);
textView.setText(myViewModel.getSelect().getName());

Fragment傳遞結(jié)果


ViewModel的生命周期

ViewModel的生命周期如圖兄春,來源官網(wǎng)

ViewModel對象存在的時間范圍是獲取ViewModel時傳遞給ViewModelProvider的Lifecycle瞒御。ViewModel將一直留在內(nèi)存中,直到限定其存在時間范圍的Lifecycle永久消失:對于Activity神郊,是在Activity完成時肴裙;而對于Fragment,是在Fragment分離時涌乳。而且蜻懦,通過ViewModel里的LiveData組件進行配合使用,還可以跟跟LifeCycle所進行關(guān)聯(lián)夕晓,當調(diào)用LiveData的observe()進行更新的時候宛乃,就可以進行生命周期的感知了。ViewModel存在的時間范圍是從您首次請求ViewModel直到Activity完成并銷毀蒸辆。
observe所需要的參數(shù)


LiveData的基本使用

在ViewModel中征炼,其實已經(jīng)用到了LiveData,我們用的是MutableLiveData躬贡,它是LiveData的實現(xiàn)類谆奥,LiveData 是一個抽象類,它的實現(xiàn)子類有 MutableLiveData 拂玻,MediatorLiveData酸些。在實際使用中,用得比較多的是 MutableLiveData檐蚜。他常常結(jié)合 ViewModel 一起使用魄懂。LiveData的使用方法也很簡單。

private MutableLiveData<String> mNameEvent = new MutableLiveData<>();

而進行監(jiān)聽的話闯第,其實剛剛在ViewModel的基本使用中也說過了市栗。

public class MyViewModel extends ViewModel {

    private MutableLiveData<List<User>> list =  new MutableLiveData<>();

    
    public void setList(MutableLiveData<List<User>> list) {
        this.list = list;
    }


    public MutableLiveData<List<User>> getList() {
        return list;
    }
}


//進行調(diào)用
MyViewModel model = ViewModelProviders.of(this).get(MyViewModel.class);
    model.getList().observe(this, new Observer<List<User>>() {
        @Override
        public void onChanged(List<User> users) {
            textView.setText(users.get(0).getName());
        }
    });

如果說你想要傳入?yún)?shù)的話,ViewModelProvider.of還有一個構(gòu)造方法,它要傳入的值就是ViewModelProvider.Factory填帽,它是一個接口蛛淋,我們可以這么寫。

public class MyViewModel extends ViewModel {

    private MutableLiveData<List<User>> list = new MutableLiveData<>();

    public MyViewModel(String key){
        User user = new User();
        user.setName(key);
        list.setValue(new ArrayList<User>());
        list.getValue().add(user);
    }

    public void setList(MutableLiveData<List<User>> list) {
        this.list = list;
    }


    public MutableLiveData<List<User>> getList() {
        return list;
    }


    public static class Factory implements ViewModelProvider.Factory {

        private String key;

        public Factory(String key) {
            this.key = key;
        }

        @NonNull
        @Override
        public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
            return (T) new MyViewModel(key);
        }
    }
}

然后直接調(diào)用就好了

//第二個參數(shù)進行傳入
MyViewModel model = ViewModelProviders.of(this, new MyViewModel.Factory("key")).get(MyViewModel.class);
model.getList().observe(this, new Observer<List<User>>() {
    @Override
    public void onChanged(List<User> users) {
        textView.setText(users.get(0).getName());
    }
});

LiveData運行結(jié)果


關(guān)于自定義LiveData

public class UserLiveData extends LiveData<User> {

    //監(jiān)聽數(shù)據(jù)
    @Override
    public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super User> observer) {
        super.observe(owner, observer);
    }

    //onPause 盲赊,onStop铣鹏, onDestroy 也會調(diào)用onChanged的回調(diào)。
    @Override
    public void observeForever(@NonNull Observer<? super User> observer) {
        super.observeForever(observer);
    }

    //回調(diào)該方法時哀蘑,表示LiveData正在被使用诚卸。
    @Override
    protected void onActive() {
        super.onActive();
    }


    //回調(diào)該方法時,表示他所有的 obervers 沒有一個狀態(tài)處理 STARTED 或者 RESUMED绘迁,注意合溺,這不代表沒有 observers。
    @Override
    protected void onInactive() {
        super.onInactive();
    }
}

關(guān)于自定義LiveData缀台,主要是重寫這幾個方法棠赛,當LiveData處于活躍狀態(tài),可以調(diào)用onActive()方法膛腐,當沒有任何觀察對象的時候睛约,就是調(diào)用onActive()方法,observeForever()的區(qū)別就是在onPause哲身、onStop辩涝、onDestroy的時候也會調(diào)用observe()onChange()方法。

參考

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末勘天,一起剝皮案震驚了整個濱河市怔揩,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌脯丝,老刑警劉巖商膊,帶你破解...
    沈念sama閱讀 221,888評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異宠进,居然都是意外死亡晕拆,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,677評論 3 399
  • 文/潘曉璐 我一進店門砰苍,熙熙樓的掌柜王于貴愁眉苦臉地迎上來潦匈,“玉大人,你說我怎么就攤上這事赚导。” “怎么了赤惊?”我有些...
    開封第一講書人閱讀 168,386評論 0 360
  • 文/不壞的土叔 我叫張陵吼旧,是天一觀的道長。 經(jīng)常有香客問我未舟,道長圈暗,這世上最難降的妖魔是什么掂为? 我笑而不...
    開封第一講書人閱讀 59,726評論 1 297
  • 正文 為了忘掉前任,我火速辦了婚禮员串,結(jié)果婚禮上勇哗,老公的妹妹穿的比我還像新娘。我一直安慰自己寸齐,他們只是感情好欲诺,可當我...
    茶點故事閱讀 68,729評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著渺鹦,像睡著了一般扰法。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上毅厚,一...
    開封第一講書人閱讀 52,337評論 1 310
  • 那天塞颁,我揣著相機與錄音,去河邊找鬼吸耿。 笑死祠锣,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的咽安。 我是一名探鬼主播伴网,決...
    沈念sama閱讀 40,902評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼板乙!你這毒婦竟也來了是偷?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,807評論 0 276
  • 序言:老撾萬榮一對情侶失蹤募逞,失蹤者是張志新(化名)和其女友劉穎蛋铆,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體放接,經(jīng)...
    沈念sama閱讀 46,349評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡刺啦,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,439評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了纠脾。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片玛瘸。...
    茶點故事閱讀 40,567評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖苟蹈,靈堂內(nèi)的尸體忽然破棺而出糊渊,到底是詐尸還是另有隱情,我是刑警寧澤慧脱,帶...
    沈念sama閱讀 36,242評論 5 350
  • 正文 年R本政府宣布渺绒,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏宗兼。R本人自食惡果不足惜躏鱼,卻給世界環(huán)境...
    茶點故事閱讀 41,933評論 3 334
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望殷绍。 院中可真熱鬧染苛,春花似錦、人聲如沸主到。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,420評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽镰烧。三九已至拢军,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間怔鳖,已是汗流浹背茉唉。 一陣腳步聲響...
    開封第一講書人閱讀 33,531評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留结执,地道東北人度陆。 一個月前我還...
    沈念sama閱讀 48,995評論 3 377
  • 正文 我出身青樓,卻偏偏與公主長得像献幔,于是被迫代替她去往敵國和親懂傀。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,585評論 2 359

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