入門文章. 本文純屬個人見解, 請謹慎閱讀.
本文回答這個問題:
Jetpack 中的 ViewModel 到底是啥, Google 希望開發(fā)者怎么用?
ViewModel
-
Google 為什么推出 ViewModel 這個東西?
從開始做 Android 開發(fā), 就有一個問題覺得不可思議: 我只不過是把屏幕旋轉了一下, 為什么我存到 Activity / Fragment 中的變量(對象\數據)就沒了呢? 難道 Android 能幫我把 view 重建, 就不能幫我把這些數據保存下來?后來我們知道, 由于 Android 發(fā)生了 config change, view 的重建意思就是 Activity Fragment 等組件, 在銷毀之后, Android 幫助我們重新創(chuàng)建了. 這是跟生命周期相關的. 然后 Android 就把數據保存的工作甩給了開發(fā)者, 告訴開發(fā)者們 你們可以用
onSaveInstanceState(outBundle: Bundle)
這個方法在組件被銷毀之前保存下來, 最后當這些組件重新創(chuàng)建的時候, 在onCreate(savedInstanceState: Bundle?)
中讀取并設置控件的值就行了.乍一看, 這沒什么毛病, 人家要銷毀你的組件了, 給你提供一組保存和重置數據的接口方法, 并且?guī)湍阒匦聞?chuàng)建了組件, 仁至義盡了對吧?
實際上, 作為菜鳥級開發(fā)者, 這對我來說實在有點太難了. 我還要記住這些方法名, 以及方法的參數有時候有值 有時候又沒有值(onCreate 方法的傳入參數, 在正常創(chuàng)建的時候為空, 在銷毀重建恢復用戶數據的時候可能不為空
). 有這時間我多想想怎么把 APP 的業(yè)務搞的更健壯不好嗎?這實際上就是 Google 在了解到開發(fā)者的痛楚之后, 為廣大的 Android 開發(fā)者提供的福利. (而我還是感覺 Google 可以做的更好, 這種生命周期對開發(fā)者來說最好是透明的, 開發(fā)者不用去關心什么時候 view重建了 我要重新賦值了 等等這些問題, 開發(fā)者只要做好業(yè)務實現, 其他都交給 framework, 這才是我心目中理想的框架實現)
那么為我們保存Activity 和 Fragment 狀態(tài)的就是: ViewModel.
ViewModel 不同于 Activity 中的實例變量. Activity 中的實例變量在Activity發(fā)生 config change 的時候被銷毀了. 而 ViewModel 對象有一個獨立的生命周期. 他不會由于 Activity 的config change而銷毀. 因此 ViewModel 這個對象是可以獨立于 Activity 的生命周期而幸存的.
簡單說就是: ViewModel 幫助開發(fā)者省去了對
onSaveInstanceState(outBundle: Bundle)
和onCreate(savedInstanceState: Bundle)
這兩個方法的顧慮.
-
ViewModel 好用嗎?
- 上面說了 ViewModel 的出現, 讓開發(fā)者省去了對狀態(tài)數據銷毀和重建的顧慮.
- 那么他好用嗎? 要是雖然不用考慮那兩個方法了, 但是需要考慮更多的細節(jié), 豈不是得不償失?
- 對! 是的! 好用! 至少不會比之前難用!
-
ViewModel 怎么用?
- 很簡單, 只要記住兩個步驟就行:
- 原來在 Activity 或 Fragment 中創(chuàng)建實例變量的地方, 改成對 ViewModel 的引用
- 創(chuàng)建一個 ViewModel 的子類, 把原來寫在 Activity 中的那些實例變量放到這個 viewModel 里面去
徒手寫代碼
- 創(chuàng)建一個 ViewModel
class MainActivityViewModel : ViewModel() {
var name: String? = null
var age: Int? = null
}
- 在 Activity 中引用
class MainActivity: AppCompatActivity() {
private lateinit var mainViewModel: MainActivityViewModel
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
mainViewModel = ViewModelProvider(this).get(MainActivityViewModel::class.java)
// mainViewModel.name = "chinalwb"
// 訪問mainViewModel.age, 操作..
// 把 mainViewModel 的值設置到控件上
}
}
- 很簡單對吧?!
- 是的.. 額! 你沒說怎么恢復已經保存的數據啊
- 嗯, 你說的非常好! 我們知道在 Activity 發(fā)生 config change 而銷毀重建的時候, onCreateView 是必定要執(zhí)行到的. 所以我們在這個方法中對 viewModel 進行初始化和數據的訪問和設定, 就完成了數據的恢復