ViewModel

  1. 可以提供和管理UI界面数据。(将加载数据与数据恢复从 Activity or Fragment中解耦)
  2. 可感知生命周期的组件。
  3. 不会因配置改变(Configuration change)而销毁。
  4. 可以配合 LiveData 使用。
  5. 多个 Fragment 可以共享同一 ViewModel。

Configuration change的情况:

  1. 屏幕旋转

Activity重建:

  1. 屏幕旋转
  2. 用户手动切换系统语言
  3. 系统内存不足,应用在后台被系统杀掉,然后用户再进入应用

    系统杀后台跟屏幕旋转最大的不同是:杀后台Activity不会走onDestory()和onRetainCustomNonConfigurationInstance()方法。

对于我个人而言,ViewModel是数据与View层还有Model层分离的手段,为什么要分离呢?第一,层次化。使得数据、视图的分层更加合理,方便管理和扩张。第二,脱离声明周期。以往数据没有分离,数据是与视图绑定的,众所周知,视图的声明周期极其复杂,数据的管理也会受到影响,所以分离就极其重要了。

  1. 管理数据,把VIEW中的数据独出来,单独进行管理
  2. 管理数据的保存与恢复,比如屏幕转动,用户点回退按钮,或切换语言等操作
  3. 可以很方便的监听到UI上的数据变化
  4. 主要和LiveData与Room组合使用

注意:ViewModel只是用来管理UI的数据的,千万不要让它持有View、Activity或者Fragment的引用(小心内存泄露)。

ViewModel数据恢复原理

当屏幕旋转或者切换系统语言时,Activity 生命周期从销毁再重建,但是ViewModel里面的变量值不受到影响,说明ViewModel中的变量在屏幕旋转前进行了存储,在屏幕旋转后又进行了恢复。

里面的原理是怎么实现的呢?

分析入口://获取viewModel
model = ViewModelProviders.of(getActivity()).get(NameViewModel.class);

ViewModelProviders.of():

  1. 保存了ViewModelStore和Factory并返回ViewModelProvider
  2. 参数1:getViewModelStore()方法中
    从Activity的NonConfigurationInstances中取ViewModelStore,取不到就new一个
    参数2:Factory中反射生成ViewModel实例

ComponentActivity

  1. onRetainNonConfigurationInstance()保存状态  转屏时自动调用
  2. getLastNonConfigurationInstance()恢复状态

Activity在横竖屏切换时悄悄保存了viewModelStore,放到了NonConfigurationInstances实例里面,横竖屏切换时保存了又恢复了回来,相当于ViewModel实例就一直在,也就避免了横竖屏切换时的数据丢失.

如果想要系统内存不足,杀掉后台,App再次回到前台,之前的数据进行恢复,应该怎么处理?