首先我們要知道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)行使用