定义:
在 Android 中,ViewModel 的作用就是在 UI 控制器( 如 Activity、Fragment)的生命周期中保存和管理 UI 相关的数据。ViewModel 保存的数据在配置更改(如屏幕旋转)后会依然存在,不会丢失。
ViewModel 类旨在以注重生命周期的方式存储和管理界面相关的数据
ViewModel的生命周期
优点:
- Activity发生屏幕旋转数据保留
- ViewModel + LiveData 实现 Activity 的多个 Fragment 之间共享数据
public class UserViewModel extends ViewModel {
private MutableLiveData<Integer> scoreData;
public MutableLiveData<Integer> getScoreData() {
if(scoreData == null){
scoreData = new MutableLiveData<>();
}
return scoreData;
}
}
class FragmentA : Fragment() {
private lateinit var userViewModel: UserViewModel
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
activity?.also {
userViewModel = ViewModelProviders.of(it).get(UserViewModel::class.java)
}
return inflater.inflate(R.layout.fragment_a, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
userViewModel.scoreData.observe(viewLifecycleOwner, Observer<Int> {
textView1.text = it.toString()
})
}
}
class FragmentB : Fragment() {
private lateinit var userViewModel: UserViewModel
private var num = 0;
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
activity?.also {
userViewModel = ViewModelProviders.of(it).get(UserViewModel::class.java)
}
return inflater.inflate(R.layout.fragment_b, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
textView1.setOnClickListener {
num++
userViewModel.scoreData.postValue(num)
}
userViewModel.scoreData.observe(viewLifecycleOwner, Observer<Int> {
textView2.text = it.toString()
})
}
}
面试题
- 为什么Activity旋转屏幕后ViewModel可以恢复数据
ViewModel 出现之前,Activity 可以使用 onSaveInstanceState() 方法保存,然后从 onCreate() 中的 Bundle 恢复数据,但此方法仅适合可以序列化再反序列化的少量数据(IPC 对 Bundle 有 1M 的限制),而不适合数量可能较大的数据。
当Activity首次创建时,它会请求一个ViewModel实例,通常是通过 ViewModelProvider 进行的。这个Provider负责实例化 ViewModel 对象,并确保在Activity或Fragment的生命周期内这些对象保持不变。如果在屏幕旋转等配置更改后Activity或Fragment被销毁并重新创建,ViewModelProvider会返回同一个ViewModel实例而不是创建一个新的实例,从而实现了数据的保留与恢复。
当Activity销毁时,系统会通过 onRetainNonConfigurationInstance() 方法将 ViewModelStore 转化为NonConfigurationInstances对象,并在Activity重建时通过 getLastNonConfigurationInstance() 方法恢复mViewModelStore实例对象,进而根据对应的key拿到销毁前对应的ViewModel实例。这种方式确保了即使在屏幕旋转等配置更改的情况下,ViewModel中的数据也能得到恢复。