作者:手机用户2502929183 | 来源:互联网 | 2023-10-11 17:10
我的应用允许用户提交表单(Androidx Fragment)以保存数据。提交表单约30次后,应用程序内存不足并崩溃。内存转储的比较表明,问题的根源之一是提交表单时,与表单片段相关联的ViewModel并未被破坏。
使用片段的onViewCreated()
方法中的'this'关键字,当前将ViewModel的作用域限定为片段:
vm = new ViewModelProvider(this).get(AddInventoryVM.class);
当用户提交表单时,通过使用“ Android体系结构组件”中的“ Android导航”来导航到同一片段,从而重新加载该片段。
navController.navigate(R.id.addInventoryFragment,null);
在此过渡期间,不会对ViewModel的实例进行垃圾回收。 onViewCreated()
被调用并创建ViewModel的新实例-多次发生时会导致内存问题。不会调用'onDestroy()
',但是在过渡期间会调用onDestroyView()
。
原因可能是Fragment实例在过渡期间未销毁(导致未对ViewModel进行垃圾回收)-仅销毁了Fragment的视图。但是,如果是这种情况,则不会增加任何东西-Android不会在过渡时重用现有的ViewModel而不是创建新的ViewModel吗?
尽管存在上述差异,将ViewModel范围限定为Fragment的ViewLifecycleowner()
是解决此问题的好方法吗?
因此要更改此内容:
vm = new ViewModelProvider(this).get(AddInventoryVM.class);
对此:
vm = new ViewModelProvider(getViewLifecycleowner()).get(AddInventoryVM.class);
按照Navigate to a destination documentation:
Android会维护一个包含您访问过的目的地的后台堆栈。当用户打开应用程序时,您的应用程序的第一个目标位于堆栈上。每次对navigate()
方法的调用都会在栈顶放置另一个目标。
因此,当您调用navController.navigate(R.id.addInventoryFragment,null);
时,您是将添加库存片段的全新实例添加到后堆栈中,这意味着您的后堆栈现在有两个副本。如果您再次致电navigate()
,则将有3个副本,然后有4个副本,等等。
您可以use popUpTo
,或者,如果您知道自己总是用它自己替换片段,请使用setLaunchSingleTop(true)
:
NavOptions optiOns= new NavOptions.Builder()
.setLaunchSingleTop(true)
.build();
navController.navigate(R.id.addInventoryFragment,null,options);
(如果您使用的是
in Navigation XML,则可以使用app:launchSingleTop="true"
做同样的事情)