MST

星途 面试题库

面试题:Kotlin Android中ViewModel的生命周期管理及内存泄漏防范

在Kotlin开发的Android应用里,ViewModel的生命周期与Activity或Fragment的生命周期有怎样的关系?在配置变更(如屏幕旋转)时,ViewModel是如何保持数据不丢失的?请分析并说明如何防止因ViewModel使用不当导致的内存泄漏问题,可举例说明。
35.4万 热度难度
编程语言Kotlin

知识考点

AI 面试

面试题答案

一键面试

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视图销毁时取消观察
    }
}