我有两个 Activity ;假设A和B。在activity A中,注册了一个广播接收器,该广播接收器侦听将完成 Activity A的特定事件。我正在onCreate()中注册该广播接收器,并在onDestroy()activity A中销毁它。

为简单起见,在button中有一个名为“销毁 Activity A”的activity B。当用户单击button时,activity A应该被销毁。

通常,所有这些操作均正常运行,没有任何问题,但是在以下情况下会出现此问题:

1)假设我使用的是activity B,然后按Home键将应用程序移至后台,那么如果我使用其他占用大量资源的应用程序,则Android系统将杀死我的应用程序以释放内存。然后,如果我从最近的任务中打开我的应用程序,将恢复activity B,并调用onCreate()onResume()等方法。现在,我按button销毁activity A,但是 Activity A已经被销毁,因此直到和除非我通过按activity A进入onCreate(),才会调用onResume()activity Aback button等方法。因此,broadcast receiver未注册以侦听该事件。

2)当用户从设备设置的“开发人员”选项中选择“不保留 Activity ”时,也会出现同样的问题。

很长时间以来,我一直在寻找解决这个问题的方法,但是我找不到合适的答案。处理这种情况的最佳方法是什么?这是Android的错误吗?对于此问题应该有一些解决方案。

请帮我。

最佳答案

在保留当前广播逻辑的同时无法解决此问题。

从后端堆栈(imo)中杀死 Activity 不是正确的方法。您应该强烈考虑更改导航逻辑。

但是,如果您的项目很大并且时间很麻烦,那么重构就不可能了。的方法有效,但是您提到您有很多 Activity 需要杀死,他的解决方案实现起来非常棘手。

我的建议如下。这可能不是最好的主意,但我想不到另一个。所以也许可以帮上忙。

您应该具有以下条件:

  • 您所有 Activity 的基本 Activity 。
  • 在应用程序级别的ArrayList<String> activitiesToKill对象。 (如果不扩展Application,则可以将其作为静态变量

  • 首先,我们必须确保当操作系统杀死内存不足的应用程序时,activitiesToKill不会丢失。在BaseActivity中,我们在onSaveInstanceState期间保存列表,并将其恢复为onRestoreInstanceState
    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putSerializable("activitiesToKill", activitiesToKill);
    }
    
    private void onRestoreInstanceState(Bundle state) {
        if (state != null) {
            activitiesToKill = (ArrayList<String>) state.getSerializable("activitiesToKill");
        super.onRestoreInstanceState(state);
    }
    

    }

    这里的想法是通过使用 Activity 名称保存哪些 Activity 应在列表中被杀死。

    逻辑如下:

    假设您有 Activity A,B,C,D和E

    在 Activity E中,按下按钮,然后想要杀死B和D

    当您按E中的按钮时,会将B和D的名称添加到activitiesToKill对象。
    activitiesToKill.add(B.class.getSimpleName()
    activitiesToKill.add(D.class.getSimpleName()
    

    在BaseActivity的onCreate方法中,我们必须检查
    if(savedInstanceState != null)
    {
        //The activity is being restored. We check if the it is in the lest to Kill and we finish it
        if(activitiesToKill.contains(this.getClass().getSimpleName()))
        {
            activitiesToKill.remove(this.getClass().getSimpleName())
            finish();
        }
    }
    

    如果 Activity 通过广播被杀死,请确保删除该 Activity 的名称。

    所以基本上这是在每种情况下都会发生的事情。

    如果应用程序正常运行,并且您单击按钮,则广播将被发送,并且B和D将被杀死。确保从activitiesToKill中删除B和D

    如果该应用程序被杀死并恢复,则按下按钮,广播将无效,但是您已将B和D添加到activitiesToKill对象中。因此,当您单击返回时,将创建 Activity ,并且saveInstanceState不为null,则 Activity 结束。

    这种方法认为 Activity E知道必须杀死哪些 Activity 。

    如果您不知道从E中杀死哪些 Activity ,则必须稍微修改以下逻辑:

    而不是使用ArrayList使用HashMap<String, bool>
    创建 Activity B后,它将自己注册到哈希图中:
    activitiesToKill.put(this.class.getSimpleName(), false)
    

    然后在 Activity E中,您要做的就是将所有条目设置为true
    然后,在基础 Activity 的创建时,您必须检查该 Activity 是否已在activityToKill中注册(哈希图包含键),并且 bool(boolean) 值是true,您将其杀死(不要忘记将其返回为false或删除键)

    这样可以确保每个 Activity 都向HashMap注册,而 Activity E并不是最了解要杀死的所有 Activity 。而且,别忘了删除它们,以防广播杀死它们。

    这种方法还可以确保从意图中正常打开该 Activity 时不会杀死该 Activity ,因为在这种情况下,onSaveInstanceState在onCreate中将为null,因此不会发生任何事情。

    如果您有需要通过不同条件终止的 Activity 组(不仅是单击按钮),则可以完成更高级的检查,以便可以使用HashMap的HashMap将它们划分为类别。

    另请注意,如果您有多个具有相同名称但 bundle 包不同的 Activity ,则可以使用getName代替getSimpleName。

    我希望我的脑子里写的很清楚,请告诉我是否有不清楚的地方。

    祝你好运

    07-28 01:45
    查看更多