引用AsyncTask found here的文档,它说:
理想情况下,
AsyncTasks应该用于较短的操作(最多几秒钟)。如果您需要让线程长时间运行,强烈建议您使用java.util.concurrent包提供的各种API,如Executor、ThreadPoolExecutor和FutureTask。
现在我的问题出现了:为什么?doInBackground()
函数在UI线程上运行,那么长时间运行的操作有什么坏处呢?
发布于 2012-10-26 14:45:56
这是一个非常好的问题,作为一名Android程序员需要时间来完全理解这个问题。实际上,AsyncTask有两个相关的主要问题:
在RoboSpice Motivations应用程序(available on Google Play)中,我们详细地回答了这个问题。它将深入介绍AsyncTasks、Loaders及其功能和缺点,并向您介绍针对网络请求的另一种解决方案: RoboSpice。网络请求是Android中的常见需求,本质上是长时间运行的操作。以下是该应用程序的摘录:
AsyncTask和活动生命周期
AsyncTasks不遵循活动实例的生命周期。如果您在Activity中启动AsyncTask并旋转设备,则Activity将被销毁并创建一个新实例。但AsyncTask不会消亡。它将继续存在,直到它完成。
当它完成时,AsyncTask不会更新新活动的UI。实际上,它会更新不再显示的活动的前一个实例。例如,如果您使用findViewById来检索活动内部的视图,这可能会导致java.lang.IllegalArgumentException类型的异常:视图未附加到窗口管理器。
内存泄漏问题
将AsyncTasks创建为活动的内部类非常方便。由于AsyncTask需要在任务完成或进行时操作活动的视图,因此使用活动的内部类似乎很方便:内部类可以直接访问外部类的任何字段。
然而,这意味着内部类将在其外部类实例上持有一个不可见的引用: Activity。
从长远来看,这会产生内存泄漏:如果AsyncTask持续很长时间,它会让活动保持“活动”,而安卓希望摆脱它,因为它不能再显示了。该活动不能被垃圾收集,这是Android保存设备资源的核心机制。
对于长时间运行的操作,使用AsyncTasks确实是一个非常非常糟糕的想法。不过,它们适用于生命周期较短的应用,比如在1秒或2秒后更新视图。
我鼓励您下载RoboSpice Motivations app,它真正深入地解释了这一点,并提供了执行一些后台操作的不同方法的示例和演示。
发布于 2012-10-09 19:00:15
为什么?
因为在默认情况下,AsyncTask
使用的线程池不是您创建的。切勿占用不是您创建的池中的资源,因为您不知道该池的要求是什么。而且,如果池的文档告诉您不要绑定不是您创建的池中的资源,就不要从该池中绑定资源,就像这里的情况一样。
特别是,从Android3.2开始,AsyncTask
默认使用的线程池(对于android:targetSdkVersion
设置为13或更高的应用程序)中只有一个线程--如果你无限期地占用这个线程,你的其他任务都不会运行。
发布于 2012-10-09 18:11:45
Aysnc任务是专门的线程,仍然意味着要与您的应用程序GUI一起使用,但同时保留UI线程的资源密集型任务。因此,当更新列表、更改视图等工作需要你执行一些抓取操作或更新操作时,你应该使用异步任务,这样你就可以将这些操作从UI线程中分离出来,但请注意,这些操作仍然以某种方式连接到UI上。
对于运行时间较长的任务,不需要UI更新,您可以使用服务,因为即使没有UI,它们也可以继续运行。
因此,对于较短的任务,请使用异步任务,因为它们可能会在您的衍生活动终止后被操作系统终止(通常不会在操作过程中终止,但会完成其任务)。对于长时间和重复性的任务,请使用服务。
有关更多信息,请参阅线程:
AsyncTask for longer than a few seconds?
和
https://stackoverflow.com/questions/12797550
复制相似问题