ViewModel的使用和原理

首先我們要知道ViewModel是什么?怎么用??jī)?nèi)部怎么實(shí)現(xiàn)的?好處是什么?

ViewModel 是一種用來(lái)存儲(chǔ)和管理UI相關(guān)數(shù)據(jù)的類(lèi)。但不同的是,它支持在系統(tǒng)配置發(fā)生改變的時(shí)候自動(dòng)對(duì)數(shù)據(jù)進(jìn)行保存。谷歌推薦我們配合 LiveData使用,當(dāng)然你也可以往里面存任何數(shù)據(jù)或者其他參數(shù)等。

為什么我們要使用ViewModel?因?yàn)閷?duì)于一些簡(jiǎn)單的數(shù)據(jù),我們可以通過(guò)在A(yíng)ctivity的 onSaveInstanceState()方法中存儲(chǔ),然后在onCreate()中進(jìn)行恢復(fù),但是這種方式只適合存儲(chǔ)少量的數(shù)據(jù),并且是能被序列化和反序列化的數(shù)據(jù)。而對(duì)那些大量的數(shù)據(jù)則不適用,比如一個(gè) User 或者 Bitmap 的 List。此外,它也使得 View 的數(shù)據(jù)持有者和 UI controller 邏輯更加分離,便于解耦和測(cè)試。

Activity配置更改重建時(shí)(比如屏幕旋轉(zhuǎn))保留數(shù)據(jù)

UI組件(Activity與Fragment、Fragment與Fragment)間實(shí)現(xiàn)數(shù)據(jù)共享。

一、ViewModel的使用

1.引入ViewModel

def lifecycle_version = "2.0.0"

// ViewModel and LiveData

implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version"

2. 簡(jiǎn)單使用起來(lái)

public class UserModel extends ViewModel {

? ? public final MutableLiveData<User> mUserLiveData = new MutableLiveData<>();

? ? public UserModel() {

? ? ? ? //模擬從網(wǎng)絡(luò)加載用戶(hù)信息

? ? ? ? mUserLiveData.postValue(new User(1, "name1"));

? ? }

? ? //模擬 進(jìn)行一些數(shù)據(jù)操作

? ? public void doSomething() {

? ? ? ? User user = mUserLiveData.getValue();

? ? ? ? if (user != null) {

? ? ? ? ? ? user.age = 1;

? ? ? ? ? ? mUserLiveData.setValue(user);

? ? ? ? }

? ? }

}

3.這時(shí)候在A(yíng)ctivity中就可以使用ViewModel了. 其實(shí)就是一句代碼簡(jiǎn)單實(shí)例化,然后就可以使用ViewModel了.

//構(gòu)建ViewModel實(shí)例

? ? ? ? final UserModel userModel = ViewModelProviders.of(this).get(UserModel.class);

? ? ? ? //讓TextView觀(guān)察ViewModel中數(shù)據(jù)的變化,并實(shí)時(shí)展示

? ? ? ? userModel.mUserLiveData.observe(this, new Observer<User>() {

? ? ? ? ? ? @Override

? ? ? ? ? ? public void onChanged(User user) {

? ? ? ? ? ? ? ? mContentTv.setText(user.toString());

? ? ? ? ? ? }

? ? ? ? });

? ? ? ? findViewById(R.id.btn_test).setOnClickListener(new View.OnClickListener() {

? ? ? ? ? ? @Override

? ? ? ? ? ? public void onClick(View view) {

? ? ? ? ? ? ? ? //點(diǎn)擊按鈕? 更新User數(shù)據(jù)? 觀(guān)察TextView變化

? ? ? ? ? ? ? ? userModel.doSomething();

? ? ? ? ? ? }

? ? ? ? });

這個(gè)時(shí)候,我們點(diǎn)擊一下按鈕(user中的age變?yōu)?5),我們可以旋轉(zhuǎn)手機(jī)屏幕(這個(gè)時(shí)候其實(shí)Activity是重新創(chuàng)建了,也就是onCreate()方法被再次調(diào)用,但是ViewModel其實(shí)是沒(méi)有重新創(chuàng)建的,還是之前那個(gè)ViewModel),但是當(dāng)我們旋轉(zhuǎn)之后,發(fā)現(xiàn)TextView上顯示的age居然還是15,,,,這就是ViewModel的魔性所在.ViewModel也常用于A(yíng)ctivity和Fragment之間進(jìn)行邏輯傳值處理等。提下ViewModel的生命周期了,它只有在A(yíng)ctivity銷(xiāo)毀之后,它才會(huì)自動(dòng)銷(xiāo)毀(所以別讓ViewModel持有Activity引用啊,會(huì)內(nèi)存泄露的). 下面引用一下谷歌官方的圖片,將ViewModel的生命周期展示的淋漓盡致.


二、ViewModel源碼解析

UserModel userModel = ViewModelProviders.of(this).get(UserModel.class);

首先看下ViewModelProviders.of(this)

這里通過(guò)factory單例工廠(chǎng)獲取factory,再看.get(MyViewModel.class)邏輯:


Java中獲取類(lèi)名主要有三個(gè)方法供我們使用:getName(),?getCanonicalName() 和getSimpleName(),通過(guò)類(lèi)名的鍵值對(duì)進(jìn)行緩存

這里進(jìn)行ViewModel的獲取,如果ViewModelStore中有緩存直接獲取緩存,如果沒(méi)有,就新創(chuàng)建一個(gè),然后再存儲(chǔ)起來(lái)返回。這里的創(chuàng)建是通過(guò)AndroidViewModelFactory,通過(guò)反射創(chuàng)建ViewModel實(shí)體類(lèi)

我們這里重點(diǎn)關(guān)注下ViewModelStore這個(gè)類(lèi),


在ComponentActivity中,onRetainNonConfigurationInstance()也具有相同的目的來(lái)處理類(lèi)似的請(qǐng)求,其主要是由于旋轉(zhuǎn)設(shè)備而更改顯示模式,進(jìn)而觸發(fā)這個(gè)方法的調(diào)用。

這里就是通過(guò)從ViewModelStrore中的一樣的key獲取同一個(gè)VIewModel來(lái)進(jìn)行數(shù)據(jù)的操作的,屏幕旋轉(zhuǎn)或者通過(guò)Fragment傳值getActivity()來(lái)進(jìn)行使用

?著作權(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)容僅代表作者本人觀(guān)點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

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