API参考说明,
理想情况下,AsyncTasks应该用于短时间操作(几秒钟) 最多。)
doInBackground的问题是否需要30秒才能使线程池用完线程?如果这就是原因,如果我确保我的应用程序永远不会有多个如此长时间运行的doInBackground同时执行,它会不会成为一个问题?
答案 0 :(得分:5)
我认为AyncTasks通常仍然依赖于产生它们的前台活动堆栈,因此,例如如果一个Activity产生AsyncTask,用户离开应用程序,然后操作系统缺少内存,它将终止Activity的进程(包括仍在运行的AsyncTask),并且只是希望你恢复状态并重新开始,如果用户恢复/返回您的应用程序。
对于运行时间较长的任务,特别是只有一个或几个的排序,您可能需要一个服务,因为即使关闭应用程序的UI以节省内存,这些任务仍然可以保留。
免责声明:我有一段时间没有进行Android编码,所以这个答案可能已经过时,或者基于对事物运作方式的错误理解。如果有最近经验的人可以发表评论确认,我会删除此警告;如果他们知道这是正确的话,欢迎高代表人员去编辑这一段。
答案 1 :(得分:5)
@Walter Mundt给出的答案是正确的。不过,我想添加一个信息补充,并给出一个指向可用于长时间运行的AsyncTask的库的指针。
AsyncTasks专为在后台进行操作而设计。并且,是的,如果您的AsyncTask持续两年,那么您将面临两个不同的问题:
RoboSpice,我想介绍的库,由@Walter Mundt提出,使用后台服务来执行这种请求。它专为网络请求而设计(可能长期运行),但它可以很容易地适应执行与网络无关的长时间运行任务。我很乐意为它添加一个补丁。
以下是AsyncTasks对长时间运行的任务不利的原因。以下推理是对RoboSpice motivations的版本的改编:该应用程序解释了为什么使用RoboSpice满足Android平台的需求。
AsyncTasks不遵循Activity实例的生命周期。如果在Activity中启动AsyncTask并旋转设备,则将销毁Activity并创建新实例。但AsyncTask不会死。它会继续生存直到它完成。
完成后,AsyncTask将不会更新新Activity的UI。实际上,它更新了之前的活动实例 不再显示。这可能导致java.lang.IllegalArgumentException类型的异常:如果你没有附加到窗口管理器的视图 例如,使用findViewById来检索Activity内的视图。
将AsyncTasks创建为活动的内部类非常方便。因为AsyncTask需要操纵视图 当Activity完成或正在进行时,使用Activity的内部类似乎很方便:内部类可以 直接访问外部类的任何字段。
然而,这意味着内部类将在其外部类实例上保存一个不可见的引用:Activity。
从长远来看,这会产生内存泄漏:如果AsyncTask持续很长时间,它会使活动“保持活动” 而Android想要摆脱它,因为它不能再显示。活动不能被垃圾收集,这是一个核心 Android的机制,以保护设备上的资源。
您可以使用一些变通方法来创建长时间运行的异步任务,并根据活动的生命周期管理其生命周期。你可以cancel the AsyncTask in the onStop method of your activity或者你可以让你的异步任务完成,而不是放松它的进度relink it to the next instance of your activity。
这是可能的,我们展示了RobopSpice的动机,但它变得复杂,而且代码并不是真正的通用。此外,如果用户离开活动并返回,您仍将失去任务的进度。 Loaders也出现了同样的问题,尽管它与上面提到的重新链接解决方法的AsyncTask相比更简单。
最好的选择是使用服务来执行长时间运行的后台任务。这正是RoboSpice提出的解决方案。同样,它专为网络设计,但可以扩展到非网络相关的东西。该库有一个large number of features。
由于infographics,您甚至可以在30秒内了解它。
将AsyncTasks用于长时间运行操作真的是一个非常糟糕的主意。然而,它们适用于短期生活,例如在1或2秒后更新视图。
我鼓励您下载RoboSpice Motivations app,它确实深入地解释了这一点,并提供了进行某些后台操作的不同方法的示例和演示。
如果您正在为非网络相关任务(例如没有缓存)寻找RoboSpice的替代方案,您还可以查看Tape。