ViewModel与Activity或Fragment生命周期的关系
- ViewModel生命周期:ViewModel的生命周期比Activity或Fragment长得多。当Activity或Fragment经历配置变更(如屏幕旋转)时,它们会被销毁并重新创建,但ViewModel不会被销毁。ViewModel会在其关联的Activity或Fragment完成(finish)或销毁(destroy)时才会被销毁。
- 关联方式:ViewModel通过
ViewModelProvider
与Activity或Fragment关联。在Activity或Fragment中获取ViewModel实例时,ViewModelProvider会检查是否已经存在一个与该Activity或Fragment关联的ViewModel实例,如果存在则返回该实例,否则创建一个新的实例。
配置变更时ViewModel保持数据不丢失的原理
- Android框架处理:在配置变更时,Android框架会保留现有的ViewModel实例,并将其重新关联到新创建的Activity或Fragment。这是通过
ViewModelStore
来实现的,ViewModelStore
是一个用于存储ViewModel实例的容器。在Activity或Fragment重建时,会从ViewModelStore
中获取之前的ViewModel实例,从而保证数据不丢失。
防止因ViewModel使用不当导致内存泄漏的方法及举例
- 避免持有Activity或Fragment的引用:如果ViewModel持有Activity或Fragment的强引用,当Activity或Fragment销毁时,由于ViewModel未销毁,会导致Activity或Fragment无法被垃圾回收,从而造成内存泄漏。例如,下面是错误示例:
class BadViewModel : ViewModel() {
lateinit var activity: Activity
// 这里持有Activity的强引用,会导致内存泄漏
}
- 正确做法:ViewModel应该只持有应用程序级别的数据和业务逻辑,避免依赖Activity或Fragment的特定实例。如果需要上下文,可以使用
Application
的上下文(因为Application
的生命周期和应用程序一样长)。例如:
class GoodViewModel(application: Application) : AndroidViewModel(application) {
// 使用AndroidViewModel获取Application上下文
// 这里不会导致内存泄漏
}
- 观察LiveData时注意生命周期:在Activity或Fragment中观察ViewModel中的LiveData时,要确保使用
observe
方法时传入的LifecycleOwner
是Activity或Fragment本身。这样当Activity或Fragment销毁时,会自动取消观察,防止内存泄漏。例如:
class MyFragment : Fragment() {
private val viewModel: MyViewModel by viewModels()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
viewModel.data.observe(viewLifecycleOwner) { data ->
// 处理数据
}
// 使用viewLifecycleOwner确保在Fragment视图销毁时取消观察
}
}