【发布时间】:2019-11-25 17:12:25
【问题描述】:
我的应用允许用户提交表单(Androidx 片段)来保存数据。表单提交约 30 次后,应用程序内存不足并崩溃。内存转储的比较表明,问题的根源之一是与表单的片段关联的 ViewModel 在提交表单时没有被破坏。
ViewModel 当前使用 Fragment 的 onViewCreated() 方法中的 'this' 关键字限定在 Fragment 的范围内:
vm = new ViewModelProvider(this).get(AddInventoryVM.class);
当用户提交表单时,会使用 Android Architecture Components 中的 Android Navigation 重新加载该 Fragment,以导航到同一 Fragment。
navController.navigate(R.id.addInventoryFragment, null);
在此过渡期间,ViewModel 的实例不会被垃圾回收。 onViewCreated() 被调用并创建了一个新的 ViewModel 实例 - 当这种情况多次发生时会导致内存问题。 'onDestroy()' 不会被调用,但onDestroyView() 在转换期间会被调用。
原因可能是 Fragment 实例在转换期间没有被破坏(导致 ViewModel 没有被垃圾收集) - 只有 Fragment 的视图被破坏。但是,如果是这种情况,那么事情就不会加起来 - Android 不会在转换时重用现有的 ViewModel 而不是创建一个新的吗?
尽管存在上述差异,但将 ViewModel 限定为 Fragment 的 ViewLifecycleOwner() 是否是解决问题的好方法?
所以改变这个:
vm = new ViewModelProvider(this).get(AddInventoryVM.class);
到这里:
vm = new ViewModelProvider(getViewLifecycleOwner()).get(AddInventoryVM.class);
【问题讨论】:
-
navigate(R.id.addInventoryFragment, null)只是为您的 Fragment 创建一个新实例(以及新 Fragment 的新 ViewModel)。是什么让您认为这会删除之前的 Fragment? -
navigate向前导航,但除非您使用popBackstack,否则您不会在没有“BACK”导航的情况下杀死以前的片段。 -
@ianhanniballake 起初,我的理解是当 Fragment 不再显示时,它会被销毁。这显然是不正确的。我们如何销毁 Fragment 和关联的 ViewModel?
标签: android android-fragments android-lifecycle