官方文档
“终于懂了“系列:Jetpack AAC完整解析(三)ViewModel 完全掌握
ViewModel 类旨在以注重生命周期的方式存储和管理界面相关的数据。ViewModel 类让数据可在发生屏幕旋转等配置更改后继续留存。
ViewModel最重要的特点是 生命周期长于Activity。
看到在因屏幕旋转而重新创建Activity后,ViewModel对象依然会保留。 只有Activity真正Finish的时ViewModel才会被清除。
添加依赖
// ViewModel
implementation 'androidx.lifecycle:lifecycle-viewmodel:2.2.0'
class MyViewModel : ViewModel() {
private val users: MutableLiveData> by lazy {
MutableLiveData>().also {
loadUsers()
}
}
fun getUsers(): LiveData> {
return users
}
private fun loadUsers() {
// 执行异步操作以获取用户。
}
}
class MyActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
//在系统第一次调用活动的onCreate()方法时创建ViewModel。
//重新创建的活动接收由第一个活动创建的相同MyViewModel实例。
//方法一:使用“by viewModels()”Kotlin属性委托来自activity-ktx工件
val model: MyViewModel by viewModels()
//方法二:使用ViewModelProvider
val viewModel = ViewModelProvider(this).get(MyViewModel::class.java)
model.getUsers().observe(this, Observer>{ users ->
// update UI
})
}
}
如果重新创建了该 Activity,它接收的 MyViewModel 实例与第一个 Activity 创建的实例相同。当所有者 Activity 完成时,框架会调用 ViewModel 对象的 onCleared() 方法,以便它可以清理资源。
注意:ViewModel 绝不能引用视图、Lifecycle 或可能存储对 Activity 上下文的引用的任何类。这样可以避免了可能的内存泄漏,同时实现了解耦。
两个 fragment 可以使用其 activity 范围共享 ViewModel 来处理此类通信
class SharedViewModel : ViewModel() {
val selected = MutableLiveData- ()
fun select(item: Item) {
selected.value = item
}
}
class ListFragment : Fragment() {
private lateinit var itemSelector: Selector
//方法一:使用“by activityViewModels()”Kotlin属性委托来自fragment-ktx
private val model: SharedViewModel by activityViewModels()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
itemSelector.setOnClickListener { item ->
// Update the UI
}
}
}
class DetailFragment : Fragment() {
//方法二:注意ViewModelProvider实例传入的是宿主Activity,requireActivity()
private lateinit var pageViewModel: SharedViewModel
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
model = ViewModelProvider(requireActivity()).get(SharedViewModel::class.java)
model.selected.observe(viewLifecycleOwner, Observer
- { item ->
// Update the UI
})
}
}
ViewModel是存在内存中,读写速度快,而通过onSaveInstanceState是在 序列化到磁盘中。
ViewModel,可以存复杂数据,大小限制就是App的可用内存。而 onSaveInstanceState只能存可序列化和反序列化的对象,且大小有限制(一般Bundle限制大小1M)。
如果 ViewModel 需要 Application 上下文(例如,为了查找系统服务),它可以扩展 AndroidViewModel 类并设置用于接收 Application 的构造函数,因为 Application 类会扩展 Context。