Sme*_*eet 25 android broadcastreceiver android-lifecycle android-activity back-stack
我有两个活动; 假设A和B activity A
是有广播接收器注册侦听将完成活动A.我注册的广播接收器的特定事件 onCreate()
,并摧毁它onDestroy()
的activity A
.
为简单起见,有一个button
在activity B
名为"破坏活性的A".当用户点击时button
,activity A
应该销毁.
通常所有这些都运行顺利,没有任何问题,但问题出现在以下场景中:
1)假设我在activity B
,我按Home键将应用程序移动到后台然后如果我使用其他资源繁重的应用程序,Android系统将杀死我的应用程序以释放内存.然后,如果我最近的任务打开我的应用程序时,activity B
将被收回,这是onCreate()
,onResume()
等方法将被调用.现在我按button
摧毁activity A
,但活动A已经被破坏,所以activity A
的onCreate()
,onResume()
等方法将不会被调用之前,除非我去activity A
按back button
.因此broadcast receiver
没有注册来监听事件.
2)当用户在设备的设置中从Developer选项中选择"Do not keep activities"时,会出现同样的问题.
我一直在寻找解决这个问题很长一段时间,但我无法找到合适的答案.处理这种情况的最佳方法是什么?这是Android的错误吗?这个问题应该有一些解决方案.
请帮我.
如果您
Activity A
已被Android操作系统本身销毁,则无法跟踪.
有些人建议Activity A
通过在onDestroy
方法BUT中列出事件来跟踪它, 如果你Activity
被系统操作系统杀死然后在这里注意它不会调用那些方法.
在保持当前广播逻辑的同时,无法修复此问题。
在我看来,从后台终止活动并不是正确的方法。您应该强烈考虑更改导航逻辑。
但是,如果您的项目很大,时间是个问题,并且重构是不可能的,那么 AJ 的方法是有效的,但是您提到您有很多活动需要终止,那么他的解决方案实施起来就会变得非常棘手。
我的建议如下。这可能不是最好的主意,但我想不出另一个主意。所以也许这会有所帮助。
您应该具备以下条件:
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);
}
Run Code Online (Sandbox Code Playgroud)
}
这里的想法是通过使用活动的名称来保存应在列表中终止的活动。
逻辑如下:
假设您有活动 A、B、C、D 和 E
在活动 E 中,您按下按钮并想要杀死 B 和 D
当您按下 E 中的按钮时,您将 B 和 D 的名称添加到对象中activitiesToKill
。
activitiesToKill.add(B.class.getSimpleName()
activitiesToKill.add(D.class.getSimpleName()
Run Code Online (Sandbox Code Playgroud)
在onCreate
BaseActivity 的方法中,我们必须检查是否
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();
}
}
Run Code Online (Sandbox Code Playgroud)
如果活动通过广播被终止,请确保删除该活动的名称。
所以基本上这就是每个场景中都会发生的情况。
如果应用程序正常运行,并且您单击按钮,则会发送广播,并且 B 和 D 将被杀死。确保从中删除 B 和 DactivitiesToKill
如果应用程序被杀死并恢复,你按下按钮,广播将没有效果,但你已经将B和D添加到对象中activitiesToKill
。因此,当您单击“后退”时,该活动已创建并且savedInstanceState不为空,该活动已完成。
这种方法认为活动 E 知道它必须杀死哪些活动。
如果您不知道要从 E 中终止哪些活动,则必须稍微修改此逻辑:
不使用 ArrayList,而是使用HashMap<String, bool>
当 Activity B 创建时,它会将自己注册到 hashmap 中:
activitiesToKill.put(this.class.getSimpleName(), false)
Run Code Online (Sandbox Code Playgroud)
然后从活动 E 中,您所要做的就是将所有条目设置为true
然后在创建基本活动时,您必须检查该活动是否在 eventsToKill 中注册(哈希图包含密钥),并且布尔值是true
您杀死它(不要忘记将其返回为 false,或删除密钥)
这确保每个活动将自身注册到 HashMap,并且活动 E 不知道要杀死的所有活动。并且不要忘记删除它们,以防广播杀死它们。
这种方法还确保从意图正常打开时活动不会被终止,因为在这种情况下 onSaveInstanceState 在 onCreate 中将为 null,因此不会发生任何事情。
如果您有需要通过不同条件(不仅仅是单击按钮)终止的活动组,则可以完成更高级的检查,以便您可以使用 HashMap 的 HashMap 将它们划分为类别。
另请注意,如果您有多个名称相同但捆绑包不同的活动,则可以使用 getName 而不是 getSimpleName。
我希望我的解释足够清楚,因为我是从我的脑海中写出来的,如果有任何不清楚的地方,请告诉我。
祝你好运
归档时间: |
|
查看次数: |
1402 次 |
最近记录: |