JetPack 之 ViewModel
ViewModel仍然是Model的範疇,是資料物件的載體,但是多了與檢視(View)生命週期的繫結關係。可以簡單理解為帶有生命週期的資料物件。可在Activity, Fragment中使用,保證其在生命週期內的唯一性和一致性,不受配置的更改(例如螢幕旋轉)。
ViewModel生命週期
下圖可以看出,ViewModel的生命週期和Activity/ Fragment一樣甚至更長,因為如果發生螢幕旋轉,ViewModel並沒有跟著銷燬,直到最終的onDestroy。

ViewModel的使用
使用Android的 ViewModel
,需要在gradle新增引用:
implementation 'android.arch.lifecycle:extensions:1.1.1'
ViewModel的宣告 千萬不能持有Context的引用,否則會引起記憶體洩漏,如果實在需要Context,可以繼承AndroidViewModel,通過getApplication()獲取Application。
public class CustomModelextends ViewModel{ public CustomObj obj;//業務內需要使用的物件 }
在程式碼中使用ViewModel。
public class MyActivityextends Activity{ public void myFunction(){ CustomModel customModel = ViewModelProviders.of(MyActivity.this).get(CustomModel.class); customModel.obj...//自己操作該物件 } }
ViewModel的實現原理
通過上面的例項我們可知 :
- 多個
ViewModel
儲存在ViewModelStore
中,本質上是一個Map
儲存的鍵值對。key
為ViewModel
的名字或者get
方法時自己設定的key
。 - 先查詢
ViewModelStore
中是否含有該例項,有則直接返回,沒有則通過反射的方式得到例項,並加入ViewModelStore
中。 -
ViewModelProviders.of(activity/fragment)
,通過activity/fragment
拿到Application
,當然AndroidViewModel
也是通過反射拿到初始例項的,和ViewModel
不同的是它需要將application
傳過去。
ViewModelStore
在 android support
包和 androidx
下儲存 ViewModel
的方式完全不同,但是暴露給我們使用的方法卻是不變的。
-
在
android support
包中的實現:-
ViewModel
本質上屬於Activity/ Fragment
級別,通過FragmentManager/ChildFragmentManager
插入一個沒有View
的HolderFragment
,ViewModelStore
即儲存在HolderFragment中
; - 在
onCreate
時setRetainInstance(true)
, 保證螢幕旋轉時fragment
不被銷燬; -
HolderFragment
在onDestroy
時回撥ViewModelStore.clear
,迴圈呼叫ViewModelStore.onCleared
。
-
-
在
androidx
包中的實現:-
ViewModel
仍然屬於Activity/Fragment
級別,只是ViewModelStore
是分別儲存在FragmentActivity
和Fragment
中; - 在
Activity
銷燬重建過程是通過onRetainNonConfigurationInstance()
、getLastNonConfigurationInstance()
儲存和還原的ViewModelStore物件的; - 在
Fragment
中的ViewModelStore
會在配置變化的時候快取在FragmentManagerNonConfig
物件(包括不被銷燬的fragment
集合,迴圈巢狀的子Fragment
的FragmentManagerNonConfig
集合以及所有Fragment
的ViewModelStore
集合),它們在FragmentActivity
重建onCreate
時還原每個Fragment
的ViewModelStore
物件,可以說ViewModelStore
的儲存介質是正常被銷燬的,只是ViewModelStore
資料被儲存並在特定場景下還原回來,儲存和還原都是由FragmentActivity
主動觸發的; - 如果是由配置更改導致
Activity/Fragment
onDestroy
則不清除ViewModelStore
的資料,反之則清除。
-
總之,不管採用不銷燬 ViewModelStore
的儲存介質,還是採用儲存再還原資料的方式,都能保證在當前作用域下資料的唯一性和完整性。