ViewModel 是個(gè)抽象類(lèi),作用是為 Activity/Fragment 這樣的視圖控制器來(lái)存儲(chǔ)和管理相關(guān)數(shù)據(jù)。
一個(gè) ViewModel 對(duì)象的創(chuàng)建會(huì)和 Activity/Fragment 的創(chuàng)建關(guān)聯(lián)起來(lái),并且隨著 Activity/Fragment 的消亡,也隨之消亡。(有一種情況比較特殊,當(dāng)屏幕旋轉(zhuǎn)造成 Activity/Fragment 生命周期重走,并不會(huì)引起 ViewModel 對(duì)象的重建。)
在數(shù)據(jù)操作上,ViewModel 的數(shù)據(jù)變更會(huì)通過(guò) LiveData 或者 DataBinding 的方式通知到 Activity/Fragment 上來(lái)展現(xiàn)。
所以實(shí)現(xiàn) MVVM 的關(guān)鍵就是 Lifecycle 的概念 + LiveData + ViewModel。
實(shí)現(xiàn)原理
老規(guī)矩,先來(lái)看看實(shí)現(xiàn)原理,以下代碼基于當(dāng)前最新的 androidx 版本 1.3.0,低版本實(shí)現(xiàn)上有所區(qū)別,不過(guò)核心思想差別不大。
ViewModel 對(duì)象的創(chuàng)建需要通過(guò) ViewModelProvider 來(lái)實(shí)現(xiàn)。根據(jù)提供的構(gòu)造方法,ViewModelStoreOwner 對(duì)象是必須提供的,
public ViewModelProvider(@NonNull ViewModelStoreOwner owner) {
this(owner.getViewModelStore(), owner instanceof HasDefaultViewModelProviderFactory ? ((HasDefaultViewModelProviderFactory) owner).getDefaultViewModelProviderFactory() : NewInstanceFactory.getInstance());
}
ViewModelStoreOwner 是個(gè)接口,描述的是 ViewModelStore 的持有者,系統(tǒng)的 ComponentActivity 就實(shí)現(xiàn)了這個(gè)接口。而 ViewModelStore 可以理解為 ViewModel 的倉(cāng)庫(kù),用來(lái)緩存 ViewModel 的,內(nèi)部實(shí)現(xiàn)是一個(gè) HashMap 類(lèi)型的集合,說(shuō)明可以存儲(chǔ)多個(gè) ViewModel 對(duì)象。
所以就以 Activity 為例,Activity 相當(dāng)于擁有者一個(gè)可以存儲(chǔ) ViewModel 的倉(cāng)庫(kù),那這個(gè)倉(cāng)庫(kù)的 ViewModel 對(duì)象具體怎么存取呢?
回看到前面的構(gòu)造方法,ViewModelProvider 還需要我們提供一個(gè) Factory 類(lèi)型的對(duì)象,結(jié)合 ComponetActivity 可以知道,它也實(shí)現(xiàn)了 HasDefaultViewModelProviderFactory 接口,接口方法要求返回一個(gè) ViewModelProvider.Factory 類(lèi)型對(duì)象,
public ViewModelProvider.Factory getDefaultViewModelProviderFactory() {
if (mDefaultFactory == null) {
mDefaultFactory = new SavedStateViewModelFactory(
getApplication(),
this,
getIntent() != null ? getIntent().getExtras() : null);
}
return mDefaultFactory;
}
這個(gè) Factory 看似是個(gè)用來(lái)生產(chǎn) ViewModel 的工廠(chǎng)定義,SavedStateViewModelFactory 是 ComponetActivity 里的具體實(shí)現(xiàn)類(lèi)。
有了工廠(chǎng)類(lèi),ViewModel 倉(cāng)庫(kù),接下來(lái)看下 ViewModelProvider 提供的 get 方法,
public <T extends ViewModel> T get(@NonNull Class<T> modelClass) {
String canonicalName = modelClass.getCanonicalName();
return get(DEFAULT_KEY + ":" + canonicalName, modelClass);
}
倉(cāng)庫(kù)里緩存需要用到 key,從這里可以知道 key 的生成和具體 ViewModel 類(lèi)名有關(guān),前面的默認(rèn) key 值是 "androidx.lifecycle.ViewModelProvider.DefaultKey"。當(dāng)然這只是默認(rèn) key 的生成方式,也可以自定義。
public <T extends ViewModel> T get(@NonNull String key, @NonNull Class<T> modelClass) {
ViewModel viewModel = mViewModelStore.get(key);
if (modelClass.isInstance(viewModel)) {
if (mFactory instanceof OnRequeryFactory) {
((OnRequeryFactory) mFactory).onRequery(viewModel);
}
return (T) viewModel;
}
if (mFactory instanceof KeyedFactory) {
viewModel = ((KeyedFactory) mFactory).create(key, modelClass);
}
mViewModelStore.put(key, viewModel);
return (T) viewModel;
}
主要邏輯就是先從倉(cāng)庫(kù)獲取指定 key 的 ViewModel 對(duì)象,如果沒(méi)有會(huì)根據(jù) mFactory 的類(lèi)型進(jìn)行創(chuàng)建,然后緩存到倉(cāng)庫(kù)中。如果獲取到了,就返回該對(duì)象。工廠(chǎng)創(chuàng)建 ViewModel 對(duì)象無(wú)非利用的就是反射機(jī)制,具體可以看下 SavedStateViewModelFactory 的 create 方法實(shí)現(xiàn)。create 方法不是我們這里重點(diǎn)關(guān)注的,這里就略過(guò)了。
走完這一套流程,我們就能獲取到指定 ViewModel 類(lèi)的對(duì)象,接下去就可以結(jié)合 LiveData 進(jìn)行數(shù)據(jù)和視圖的控制。下面是我分析時(shí)的一張圖,按我的理解畫(huà)了一下各自關(guān)系,便于理解。

MVVM
再來(lái)說(shuō)說(shuō) MVVM 的架構(gòu)模式,它是基于 MVP 的一種改進(jìn),因?yàn)殡S著業(yè)務(wù)的增多,導(dǎo)致 p 層的膨脹臃腫,變的難以維護(hù)。所以將 P 層改為 VM 層,實(shí)現(xiàn) VM 和 V 層還有 M 層的雙向綁定,即 V 層的變動(dòng)會(huì)使得 VM 引起 M 層的變更,M 層的變動(dòng)也會(huì)使 VM 通知 V 層進(jìn)行更新。不僅靈活度增加了,p 層也被拆分化簡(jiǎn)。
具體的化簡(jiǎn)是怎么實(shí)現(xiàn)呢?結(jié)合 Lifecycle,LiveData,ViewModel,我對(duì) MVVM 的實(shí)現(xiàn)是這么理解的。V 層依然是 Activity/Fragment,M 層管理的數(shù)據(jù)來(lái)源,但實(shí)際項(xiàng)目中不會(huì)分的那么細(xì)致,例如會(huì)融合到 P 層上。因?yàn)?VM 層代替了原來(lái)的 P 層,因此 VM 層的實(shí)現(xiàn)會(huì)有多個(gè) ViewModel 類(lèi)來(lái)管理。
為什么是多個(gè) ViewModel 類(lèi)對(duì)應(yīng)一個(gè) V 層呢?我的理解是,首先 V 層對(duì)應(yīng)的實(shí)現(xiàn)一般會(huì)持有一個(gè) ViewModel 倉(cāng)庫(kù),這個(gè)倉(cāng)庫(kù)可以存放多個(gè) ViewModel 對(duì)象。其次,ViewModel 的劃分并不像 P 層,更合理的劃分是和數(shù)據(jù)模型相關(guān),例如 UserViewModel 就是用來(lái)管理 User 數(shù)據(jù)的,ClassViewModel 就是用來(lái)管理 Class(課程)數(shù)據(jù)的。所以這樣就會(huì)使得 V 層對(duì)應(yīng)著 1 到 多個(gè) ViewModel。
這樣的好處是,1. 數(shù)據(jù)管理更清晰,2. ViewModel 可以在整個(gè)項(xiàng)目中復(fù)用,而不像 P 層,可能只能給這個(gè) V 層用。缺點(diǎn)是,代碼量又要增加了,可能 ViewModel 維護(hù)的數(shù)據(jù)模型很基礎(chǔ)很簡(jiǎn)單,但也要為其做一些維護(hù)。
當(dāng)然一個(gè) ViewModel 里也可以維護(hù)著多個(gè) LiveData(即維護(hù)多個(gè)數(shù)據(jù)模型),但這樣的話(huà)感覺(jué)就和 MVP 的思想沒(méi)什么區(qū)別了。