安卓:OutOfMemory 错误和回溯堆栈

2022-09-04 01:21:23

以下工作表表示此问题所涉及的应用程序中的工作流程。

workflow

我遇到了 OutOfMemory Errors 的问题,主要是因为用户能够多次从活动 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 将被销毁,并创建新的 Backstack(MainMenu、C、D)。这解决了我在api级别大于10的内存问题,但不幸的是,TaskStackBuilder不会为api 11之前的设备创建回堆栈。

任何想法如何避免用户在api 11之前堆叠无限数量的活动?这是否可能,或者我应该尝试在 onPause 中释放尽可能多的资源,以便在 OoM 之前获得最大数量的堆叠活动?

提前致谢!


答案 1

试试这个-

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

另一个解决方案是-

对清单文件中的活动进行设置时,只要将活动导航离开,就会从堆栈中删除该活动。android:noHistory="true"

但最合适的方法是在启动新活动时调用 method,如下面的示例代码所示-finish()

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

您还可以创建自定义广播接收器,并将其注册到每个活动中,这些活动可以在您选择的事件中触发。如需更多帮助,请查看此链接


答案 2

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_TOPIntent.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);

推荐