Android:OutOfMemory错误和后退堆栈

14
以下表格显示了应用程序中此问题的工作流程。 workflow 我遇到了OutOfMemory错误的问题,主要是因为用户能够多次从B活动切换到D活动(每次都会显示不同的内容),而之前的活动没有被销毁。这导致了一个非常大的返回堆栈,从而导致OutOfMemory错误。
为了避免这种情况,我遵循了建议,在清单中添加父活动,并使用TaskStackBuilder类创建新的返回堆栈。
void openDFromB()
{
    Intent i = new Intent(this, ActivityD.class);
    TaskStackBuilder.create(this)
        .addParentStack(ActivityD.class)
        .addNextIntent(i)
        .startActivities();
}
如果用户现在从活动B切换到D,MainMenu、A和B将被销毁,并创建一个新的后退栈(MainMenu、C、D)。这解决了我在API级别大于10时的内存问题,但不幸的是,TaskStackBuilder不会为先前API 11的设备创建后退栈。
有什么办法可以避免在API 11之前的用户堆积无限数量的活动吗?这是否可能,或者我应该尝试在onPause中释放尽可能多的资源,以获得最大数量的堆叠活动,然后再发生OutOfMemory错误?
提前感谢您!
5个回答

9

试一下这个方法-

Intent intent = new Intent(getApplicationContext(),yourActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);

另一种解决方案是——在清单文件中设置 android:noHistory="true",这将使每当一个活动被导航离开时,它都会从堆栈中移除。
但最合适的方法是在启动新活动时调用 finish() 方法,就像以下示例代码一样。
Intent intent = new Intent(this, yourActivity.class);
startActivity(intent);
finish();

你还可以创建自定义广播接收器并在每个活动中注册它,以在您选择的事件发生时触发它。 点击此链接获取更多帮助。


7
Zabri的回答很好,但我想提出另一个可能更好的解决方案:您不需要关闭每个活动,但是当您打开之前已经打开的新活动时,您要告诉系统可以清除以前的活动并重新打开那一个,当然还要使用新的意图和所有新的数据。
所以,如果您执行 A - B - D - B - D - B,而不是有一个大堆栈,您将有
1. A-B 2. A-B-D 3. A-B 4. A-B-D 5. A-B
因此,如果您执行 C - D - B - D - B - D,您的堆栈将是:
1. C-D 2. C-D-B 3. C-D 4. C-D-B 5. C-D
等等。通过这种方式,我认为堆栈实际上反映了用户心中的想法,并且导航非常合乎逻辑,您甚至不需要捕获返回按钮即可使导航有意义(当然,如果您想要更具体的用户体验,则可以这样做)。
要实现此目标的代码是:创建一个接收类(例如ActivityD.class)的函数,在其中创建一个带有标记Intent.FLAG_ACTIVITY_CLEAR_TOP和Intent.FLAG_ACTIVITY_NEW_TASK的意图,然后在需要打开活动时只需调用此函数。您不必担心该活动是否在堆栈中。如果它不存在,则会正常创建。
 protected void startActivity(Class<?> clase) {
    final Intent i = new Intent(this, clase);
    int flags = Intent.FLAG_ACTIVITY_CLEAR_TOP;
    flags |= Intent.FLAG_ACTIVITY_NEW_TASK;
    i.setFlags(flags);
    startActivity(i);
}


startActivity(ActivityD.class);

3

1
活动不会被Android销毁以回收堆空间,这是一个常见的误解。只有当应用程序暂停并且系统内存不足时,才会销毁活动。 - danijoo

2

我不知道导航抽屉如何工作,但是我之前创建了一个Android应用程序,它从加载屏幕开始,然后转到应用程序的主活动。由于我不需要/希望用户回到加载屏幕,所以在转到主活动之前我只需调用finish()即可。就像这样:

Intent intent = new Intent(this, MainActivity.class);
startActivity(intent);
finish();

当用户从主活动按下“返回”按钮时,他们没有进入加载活动,而是回到之前的位置。

因此,您也可以尝试这样做:

void openDFromB()
{
    Intent i = new Intent(this, ActivityD.class);
    startActivity(i);
    finish();
}

如我所说,我从未实现过导航抽屉,但有些东西告诉我这样做可能会破坏其整体行为。此外,在活动中调用finish()是一个非常基本的概念,如果你还没有尝试过它,我会感到惊讶的。 :) 但是,出于无奈之举,我还是发布了它,以防它能帮助到你。祝你好运。 :)


2
你好,你可以尝试在manifest文件的应用程序标签下添加以下语句:
android:largeHeap="true"

同时确保你的 android:targetSdkVersion 为14。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接