在onDestroy中进行所有清理工作是否安全?

13
更具体地说:在 onDestroy 中取消任务是否安全?同时,在 onDestroy 中注销广播接收器和释放资源是否安全?
我的目的是确保当 Activity 被销毁时,我的任务被取消或销毁,但不是在之前。
onDestroy():
1. 当 Activity 被销毁并且需要释放资源时调用。 2. 当系统低内存等情况下,Activity 被急速销毁时,不会调用。
第一种情况很清楚:我在 onDestroy 中进行所有清除操作,没有问题。然而,第二种情况有些问题。当 Activity 被销毁并且跳过 onDestroy(因此我没有取消我的任务)时,任务是否可能继续执行,然后完成并尝试更新已经销毁的 Activity,导致应用程序崩溃?
我们来到了真正的问题:
1. 当 Activity 被杀死并且 onDestroy 被跳过时,与该 Activity 相关的所有内容是否自动销毁?(仅在一切都将被彻底清除的情况下,才会跳过 onDestroy 吗?任务、注册的接收器等) 2. 如果跳过 onDestroy,这是否意味着整个应用程序都被杀死?
让我们专注于 onDestroy(),因为解决方案不在 onPause() 或 onStop() 中。理由如下:
1. 当 Activity 被销毁时,onStop() 可能会被跳过,就像 onDestroy 一样。 2. onPause 被调用得太早和太频繁,因此不适合该用例。例如:
屏幕锁定:当设备屏幕被锁定时,可能会调用 onPause。通常这种情况像一个屏幕保护程序一样,用户立即解锁,因为他正站在那里看着屏幕。在这种情况下取消任务和停止我的应用程序正在执行的所有操作,只会降低用户体验。我不希望我的应用程序因偶然的“屏幕保护程序”而窒息和表现不良。
在我的示例应用程序中,有两个作为 Activity 的屏幕。用户可以快速在它们之间切换。在这个应用程序中,用户倾向于经常且快速地切换屏幕。

导航: 其中一个屏幕有一个地图,可以接收系统的位置更新。它记录了位置变化(路线)的精确图形日志,因此需要不断运行直到 Activity 被关闭。通常我会在 onResume 和 onPause 中注册和注销任何接收器。但是,这会使应用程序非常难以使用,因为用户导航时地图上的更新会停止。因此,我希望在 onDestroy 中注销接收器。

加载列表: 第二个屏幕有一个列表,显示来自网络服务的数据。下载数据需要 4 秒钟。我使用 AsyncTask,知道应该在必要时取消它。它不应该在 onPause 中被取消,因为当用户在屏幕之间切换时,它应该继续加载。因此,我希望在 onDestroy 中取消它。

还有许多例子。其中一些可能并不完全适合每个人的观点(你甚至可以建议使用服务而不是 AsyncTask)。但是,思想很重要,所有这些例子都具有相同的思想:在 暂停 Activity 的同时继续执行特定于 Activity 的工作,但确保在 销毁 Activity 时停止它。 (无论我使用 AsyncTask 还是 Service,都应在销毁 Activity 时停止工作。)

P.S. 如果答案是在 onDestroy 中进行清理不安全,这意味着 Android 框架要求我们在 onPause 中停止我们正在做的所有事情。那么我就看不到使用 onDestroy 的任何理由了......

3个回答

1

我想向您介绍这个宝贝:http://developer.android.com/reference/android/content/ComponentCallbacks2.html#onTrimMemory(int)

基本上,它为你提供了系统找到有用的取消任务和清理内存的所有位置:

请仔细查看以下两种情况:

TRIM_MEMORY_UI_HIDDEN - 进程一直在显示用户界面,现在不再显示。

TRIM_MEMORY_COMPLETE - 进程接近后台LRU列表的末尾。

这些是你所问的大多数情况。

在同一个方法中,您还可以捕获TRIM_MEMORY_RUNNING_CRITICAL,这将提醒您系统没有内存并且必须立即采取特殊操作的情况。

在类似的情况下,这个方法使我的开发生活更加美好。


谢谢,我不确定能否直接应用于我的情况,但它确实看起来很有趣。 - Stan

1
如果你只需要进行一些清理工作,无论活动如何关闭,你都应该能够使用onSaveInstanceState()onDestroy()的组合。其中一个应该被调用,不管发生什么情况。也许在你的活动中有一个boolean cleanupDone,当两者之一完成时设置它。
关于保存用户数据,请查看保存持久状态
谷歌建议采用“原地编辑”用户模型。即:尽早保存用户创建的新数据,最晚在onPause()中完成。这并不意味着你需要在onResume()中重新创建数据,只是它应该已经被保存了。
顺便提一下:onStop()只有在Honeycomb版本之前的设备上才能被跳过,也就是说,截至2015年6月,所有设备中不到6%的设备可以跳过。但是,如果省略了onDestroy()onStop(),仍应调用onSaveInstanceState()

0

就我在Android方面的经验而言,

1 当您的应用程序崩溃时,与其相关的所有资源都会被销毁。

2 当设备更改配置导致Activity被销毁和重新创建时。

3 当应用程序在后台运行且Android由于低内存而将其关闭时。

除此之外,其他回调方法也会被调用,例如

1 当另一个Activity出现在前面时,或者您的设备锁定等等

在所有情况下,根据您的要求,您可以在onDestroy中释放所有资源并取消线程和Asyntask以及停止所有服务等。如果您希望在调用destroy时保持任务暂停和活动状态,则可以保存配置并通过检查是否为空来在再次调用onCreate时保留它。


谢谢您的回答,但问题在于当活动被销毁时,onDestroy并不总是被调用,特别是在低内存情况下。那么我该如何确保释放所有资源呢?这就是我的问题所在。(关于第二点的附注 - 活动会被重新创建,但如果您保留对旧实例的引用,则旧实例将继续存在。) - Stan
在UI线程中运行的东西会被销毁,而其他的像您自己创建的线程、异步任务和服务则会保持活动状态。 - Vipin Sahu

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