3

API 参考声明,

理想情况下,AsyncTasks 应该用于短操作(最多几秒钟。)

doInBackground 是否存在问题,例如,线程池可能会在 30 秒内耗尽线程?如果这就是原因,如果我确保我的应用程序永远不会同时执行超过一个这样长时间运行的 doInBackground ,它会不再是一个问题吗?

4

2 回答 2

6

@Walter Mundt 给出的答案是正确的。不过,我想补充一些信息,并提供一个指向可用于长时间运行 AsyncTask 的库的指针。

AsyncTasks 是为在后台做事而设计的。而且,是的,如果您的 AsyncTask 持续两个很长时间,那么您将面临 2 个不同的问题,这是正确的:

  1. 活动与活动生命周期的联系很差,如果活动终止,您将无法获得 AsyncTask 的结果。确实,是的,你可以,但这将是一种粗略的方式。
  2. AsyncTask 没有很好的文档记录。asynctask 的简单但直观的实现和使用会很快导致内存泄漏。

RoboSpice是我想介绍的库,由@Walter Mundt 提出,它使用后台服务来执行此类请求。它是为网络请求而设计的(本质上可能长时间运行),但它可以很容易地适应执行与网络无关的长时间运行的任务。我很乐意为其添加补丁。

这就是为什么 AsyncTasks 不适合长时间运行的任务的原因。以下推理改编自 RoboSpice动机的摘录:解释为什么使用 RoboSpice 的应用程序满足了 Android 平台上的需求。

AsyncTask 和 Activity 生命周期

AsyncTasks 不遵循 Activity 实例的生命周期。如果您在 Activity 中启动 AsyncTask 并旋转设备,则 Activity 将被销毁并创建一个新实例。但是 AsyncTask 不会死。它将继续存在,直到完成。

当它完成时,AsyncTask 不会更新新 Activity 的 UI。实际上,它会更新不再显示的活动的前一个实例。这可能会导致 java.lang.IllegalArgumentException: View not attach to window manager 类型的异常,例如,如果您使用 findViewById 来检索 Activity 中的视图。

内存泄漏问题

将 AsyncTasks 创建为活动的内部类非常方便。由于 AsyncTask 需要在任务完成或正在进行时操作 Activity 的视图,因此使用 Activity 的内部类似乎很方便:内部类可以直接访问外部类的任何字段。

然而,这意味着内部类将在其外部类实例上持有一个不可见的引用:Activity。

从长远来看,这会产生内存泄漏:如果 AsyncTask 持续很长时间,它会保持活动“活动”,而 Android 想要摆脱它,因为它不再显示。Activity 不能被垃圾收集,这是 Android 在设备上保留资源的中心机制。

您的任务进度将丢失

您可以使用一些变通方法来创建一个长时间运行的异步任务,并根据活动的生命周期管理其生命周期。您可以在活动的 onStop 方法中取消 AsyncTask ,也可以让您的异步任务完成,并且不会丢失其进度并将其重新链接到您的下一个活动实例

这是可能的,我们展示了 RobopSpice 的动机,但它变得复杂并且代码不是真正通用的。此外,如果用户离开活动并返回,您仍然会丢失任务的进度。Loaders 也会出现同样的问题,尽管它更简单地等同于 AsyncTask 以及上面提到的重新链接解决方法。

使用 Android 服务

最好的选择是使用服务来执行您长时间运行的后台任务。而这正是 RoboSpice 提出的解决方案。同样,它是为网络设计的,但可以扩展到非网络相关的东西。这个库有大量的特性

借助信息图表,您甚至可以在 30 秒内了解它。


将 AsyncTasks 用于长时间运行的操作确实是一个非常非常糟糕的主意。不过,它们适用于短暂的生命周期,例如在 1 或 2 秒后更新视图。

我鼓励您下载RoboSpice Motivations 应用程序,它确实深入地解释了这一点,并提供了执行某些后台操作的不同方法的示例和演示。


如果您正在为非网络相关任务(例如没有缓存)寻找 RoboSpice 的替代品,您还可以查看Tape

于 2012-10-30T21:21:59.337 回答
5

我相信 AyncTasks 通常仍然与产生它们的前台活动堆栈相关联,因此,例如,如果 Activity 产生 AsyncTask,用户离开应用程序,然后操作系统内存不足,它将终止 Activity 的进程(包括仍在运行的 AsyncTask),并且只希望您恢复状态并在用户恢复/返回您的应用程序时重新开始。

对于运行时间较长的任务,尤其是只有一个或几个的任务,您可能需要一个服务,因为即使您的应用程序的 UI 被关闭以节省内存,这些任务也可以持续存在。

免责声明:我有一段时间没有进行 Android 编码了,所以这个答案可能已经过时或者基于对事物如何工作的错误理解。如果有较新经验的人可以发表评论以确认,我将删除此警告;如果高级代表知道这是正确的,欢迎直接编辑这一段。

于 2012-08-31T17:35:48.100 回答