当内存不足时,Android不会停止堆栈中的活动
我们一直在开发一个应用程序,它有一个下拉式仪表板,允许用户在整个应用程序中导航。导航不是很标准,因为几乎每个活动都可以访问此菜单。 使用菜单打开活动播放一段时间后,堆栈开始不断增长 所有这些活动都包含包含多个图像视图的列表视图,每个视图大约占用3mb。如果用户玩得足够多,并在堆栈上创建超过25个活动,则会发生以下情况:当内存不足时,Android不会停止堆栈中的活动,android,android-activity,out-of-memory,Android,Android Activity,Out Of Memory,我们一直在开发一个应用程序,它有一个下拉式仪表板,允许用户在整个应用程序中导航。导航不是很标准,因为几乎每个活动都可以访问此菜单。 使用菜单打开活动播放一段时间后,堆栈开始不断增长 所有这些活动都包含包含多个图像视图的列表视图,每个视图大约占用3mb。如果用户玩得足够多,并在堆栈上创建超过25个活动,则会发生以下情况: 抛出内存不足错误(堆增加,直到不再有堆) 由于异常而显示对话框(很遗憾,%activity%已停止) 抛出OutOfMemorr的活动已完成 堆栈中的所有活动都已完成,但保留了历
finish()
将取消分配您要离开的活动。这将阻止您使用“后退”按钮访问它,但它会降低内存
我希望系统在抛出OutOfMemoryError之前自动终止堆栈中最早的活动
Android并没有做到这一点。Android终止进程以释放系统内存供其他进程使用。它不会以类似的方式参与应用程序内部内存的使用
我们如何告诉Android操作系统,如果需要,它可以释放活动及其资源,这样我们就不会出现“不幸的是,您的活动已经停止”对话框
你不能
相反,您需要将应用程序设计为使用更少的活动,或者每个活动使用更少的资源。例如,您可以通过“回收”现有活动实例,或者(正如Tornquist先生指出的那样),您可以自己手动finish()
活动
使用菜单打开活动播放一段时间后,堆栈开始不断增长
您可能应该在这些菜单项上使用
FLAG\u ACTIVITY\u REORDER\u TO\u FRONT
,这样您就可以在任务中推进现有的活动,而不是每次都创建新的活动。根据android开发者指南,我也有这样的印象,即系统将杀死旧的活动以释放内存:
“当系统停止您的一项活动时(例如,当新活动开始或任务移到后台时),如果需要恢复系统内存,系统可能会完全销毁该活动。发生这种情况时,有关活动状态的信息将丢失。如果发生这种情况,系统仍然知道该活动在后堆栈中有一个位置,但当该活动到达堆栈顶部时,系统必须重新创建它(而不是继续)。为了避免丢失用户的工作,您应该通过在活动中实现onSaveInstanceState()回调方法来主动保留它。”
见链接:
使用意向标志\u活动\u重新排序\u至\u前端
Intent i = new Intent(ActivityD.this, ActivityA.class);
i.setFlags(FLAG_ACTIVITY_REORDER_TO_FRONT);
startActivity(i);
这将简单地将ActivityA带到堆栈的前面,并将B和C保留在我认为您需要的位置。然后,如果您想将其从堆栈中删除,显然可以调用D上的finish()。是正确的,此外,您可以尝试此策略来释放堆栈底部活动的内存:
- 删除所有片段和/或
setContentView(null)
:调用onResume
,或者只需创建新的片段实例并将其添加回视图层次结构活动#recreate()
onLowMemory
,ontrimmory
。因为只有在整个系统内存不足时才会调用这些事件,所以在此之前,应用程序可能会内存不足。如果进程占用了太多内存,您必须跟踪进程的内存使用情况,并采取适当的措施:
val maxMemory = Runtime.getRuntime().maxMemory()
val freeMemory = Runtime.getRuntime().freeMemory()
val totalMemory = Runtime.getRuntime().totalMemory()
val remainMemoryPercent = (freeMemory + maxMemory - totalMemory) * 100f / maxMemory
// check remainMemoryPercent and take action
谢谢,您的解决方案应该可以工作,但它也会从堆栈中删除已销毁的活动。我将遵循Commonware的建议,因为历史记录中至少保存了一个此类活动。谢谢!现在我们将使用建议的标志\u activity\u REORDER\u TO\u FRONT并实现onNewIntent回调,以确保活动得到更新有了新的意图。@commonware,doc确实说可以从堆栈中删除特定的活动。“暂停的活动完全处于活动状态(…),但在内存极低的情况下可以被系统删除。”和“(停止的活动)仍然保留所有的状态和成员信息,但是,它不再对用户可见,因此它的窗口被隐藏,并且当其他地方需要内存时,它通常会被系统杀死。”(链接)。这正是“不保持活动”的方式工具也能工作…@Alesqui:Android只会在终止整个过程时才这样做。但正如几个月前公认的答案所指出的,情况并非如此。
val maxMemory = Runtime.getRuntime().maxMemory()
val freeMemory = Runtime.getRuntime().freeMemory()
val totalMemory = Runtime.getRuntime().totalMemory()
val remainMemoryPercent = (freeMemory + maxMemory - totalMemory) * 100f / maxMemory
// check remainMemoryPercent and take action