Android之MVVM架構(gòu)指南(五):ViewModel

ViewModel 是Android 架構(gòu)組件中負(fù)責(zé)管理UI相關(guān)數(shù)據(jù)與邏輯的,它的功能定義與MVP架構(gòu)中的Persenter十分相似,配合其他組件使用增加許多方便開發(fā)的功能。

基本使用

定義一個(gè)ViewModel只需要繼承ViewModel抽象類即可:

public class MainViewModel extends ViewModel {
   
}

然后我們就可以在activity/fragment中實(shí)例化它:

MainViewModel viewModel = ViewModelProviders.of(this).get(MainViewModel.class);

注意:如果想要正常使用ViewModel的全部功能,不能直接new出ViewModel的實(shí)例,而是使用ViewModelProvider類創(chuàng)建,上面的ViewModelProviders其實(shí)就是對(duì)ViewModelProvider的包裝類。

正是因?yàn)橥ㄟ^ViewModelProvider創(chuàng)建ViewModel的方式,ViewModel才具備了一些比較方便實(shí)用的功能。

生命周期

因?yàn)閯?chuàng)建ViewModel時(shí)傳入了activity/fragment對(duì)象實(shí)例(ViewModelProviders.of(this)),所以ViewModel可以感知宿主的生命周期。

當(dāng)宿主onDestroy()時(shí)候ViewModel便會(huì)自行銷毀掉,除此之前,當(dāng)屏幕旋轉(zhuǎn)的時(shí)候,Activity會(huì)被recreate,Activity會(huì)經(jīng)過幾個(gè)生命周期方法,但是這個(gè)時(shí)候ViewModel還是之前的對(duì)象,并沒有被重新創(chuàng)建。

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

public class MainViewModel extends ViewModel{

}

public class Fragment1 extends Fragment{
    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        MainViewModel ViewModel = ViewModelProviders.of(getActivity()).get(MainViewModel.class);
    }
}

public class Fragment2 extends Fragment{
    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        MainViewModel ViewModel = ViewModelProviders.of(getActivity()).get(MainViewModel.class);
    }
}

上面的例子中,如果fragment1和fragment2的宿主activity是同一個(gè)的話,那么它們創(chuàng)建的ViewModel是同一個(gè),ViewModel中的數(shù)據(jù)二者可以共享。

更新UI

ViewModel配合LiveData使用可以做到在不持有activity任何引用的情況下更新UI數(shù)據(jù),這是整個(gè)組件架構(gòu)中最有亮點(diǎn)以及最有特色的地方。

public class MainViewModel extends ViewModel{
    MutableLiveData<String> data = new MutableLiveData<>();

    public LiveData<String> getData(){
        return data;
    }

    public void loadData(){
        // 模擬一個(gè)數(shù)據(jù)請(qǐng)求
        data.setValue("test");
    }

}

public class Fragment1 extends Fragment{
    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        MainViewModel ViewModel = ViewModelProviders.of(this).get(MainViewModel.class);
        ViewModel.getData().observe(this,new Observer(){
            @Override
            public void onChanged(String s){
                textView.setText(s);
            }
        });
    }
}

在上面的例子中,textView會(huì)根據(jù)數(shù)據(jù)源的變化更新自己,而ViewModel中不需要考慮UI更新的問題,只需要關(guān)注數(shù)據(jù)的變化即可。

注意事項(xiàng)

ViewModel看似使用簡(jiǎn)單,但是在實(shí)際使用中會(huì)有一些點(diǎn)需要關(guān)注的。

1. 數(shù)據(jù)源的初始化

ViewModel本質(zhì)上就是管理各種LiveData數(shù)據(jù)源的,但一定要注意的是在外界getData()前一定要初始化數(shù)據(jù)源,因?yàn)橥饨绔@得數(shù)據(jù)源后一般會(huì)直接注冊(cè)觀察者,如果這時(shí)候數(shù)據(jù)源沒有初始化就會(huì)空指針異常。

2. 數(shù)據(jù)源的更新

上面的例子中loadData()方法更新數(shù)據(jù)源是直接用當(dāng)前data對(duì)象更新的,但是在實(shí)際使用中每次請(qǐng)求數(shù)據(jù)后極有可能會(huì)發(fā)生數(shù)據(jù)請(qǐng)求模塊返回一個(gè)新的LiveData實(shí)例,這種情況不能直接將當(dāng)前的data重新賦值:

data = newData;

這樣寫的話外界設(shè)置的觀察者就會(huì)失效了。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容