引用此处找到的AsyncTask文档,它说:
理想情况下,应将AsyncTasks用于较短的操作(最多几秒钟)。如果需要使线程长时间运行,则强烈建议您使用java.util.concurrent pacakge提供的各种API,例如执行程序,ThreadPoolExecutor和FutureTask。
现在我的问题出现了:为什么?该doInBackground()
函数运行在UI线程之外,因此如果在此处长时间运行该操作有何危害?
引用此处找到的AsyncTask文档,它说:
理想情况下,应将AsyncTasks用于较短的操作(最多几秒钟)。如果需要使线程长时间运行,则强烈建议您使用java.util.concurrent pacakge提供的各种API,例如执行程序,ThreadPoolExecutor和FutureTask。
现在我的问题出现了:为什么?该doInBackground()
函数运行在UI线程之外,因此如果在此处长时间运行该操作有何危害?
Answers:
这是一个非常好的问题,作为Android程序员,需要花费一些时间才能完全理解该问题。确实,AsyncTask有两个相关的主要问题:
在RoboSpice Motivations应用程序(可在Google Play中获得)中,我们详细回答了该问题。它将深入介绍AsyncTasks,加载程序,它们的功能和缺点,并向您介绍网络请求的替代解决方案:RoboSpice。网络请求是Android中的常见要求,并且本质上是长期运行的操作。这是该应用的摘录:
AsyncTasks不遵循Activity实例的生命周期。如果在“活动”中启动AsyncTask并旋转设备,则“活动”将被销毁并创建一个新实例。但是AsyncTask不会死。它会继续生活直到完成。
完成后,AsyncTask将不会更新新Activity的UI。实际上,它更新了不再显示的活动的前一个实例。这可能导致java.lang.IllegalArgumentException类型的异常:如果您使用例如findViewById在Activity中检索视图,则视图未附加到窗口管理器。
将AsyncTasks创建为您的Activity的内部类非常方便。由于在任务完成或正在进行时AsyncTask将需要操纵Activity的视图,因此使用Activity的内部类似乎很方便:内部类可以直接访问外部类的任何字段。
但是,这意味着内部类将在其外部类实例(活动)上保留一个不可见的引用。
从长远来看,这会导致内存泄漏:如果AsyncTask持续很长时间,它将使活动保持“活动状态”,而Android希望摆脱它,因为它不再显示。该活动不能被垃圾收集,这是Android在设备上保留资源的主要机制。
将AsyncTasks用于长时间运行的操作确实是一个非常非常糟糕的主意。不过,它们适合短暂的工作,例如在1或2秒后更新视图。
我鼓励您下载RoboSpice Motivations应用程序,它确实对此进行了深入的解释,并提供了一些示例和演示有关进行某些后台操作的不同方式。
为什么呢?
因为AsyncTask
默认情况下使用的不是您创建的线程池。切勿占用未创建的池中的资源,因为您不知道该池的要求是什么。如果该池的文档告诉您不这样做,则切勿占用未创建的池中的资源,如此处所示。
特别是从Android 3.2开始,AsyncTask
默认情况下使用的线程池(对于android:targetSdkVersion
设置为13或更高版本的应用程序)仅包含一个线程-如果无限期地占用该线程,则其他任何任务都不会运行。
Service
,只需使用a Thread
或a ThreadPoolExecutor
。
TimerTask
来自标准Java,而不是Android。TimerTask
已在很大程度上被弃用ScheduledExecutorService
(尽管它的名字,它是标准Java的一部分)。两者都与Android无关,因此,如果您希望这些事情在后台运行,那么您仍然需要一项服务。而且,您确实应该考虑AlarmManager
使用Android,因此您不需要仅在时钟上滴答作响的服务。
Aysnc任务是专用线程,仍将与您的应用程序GUI一起使用,但同时保留UI线程的大量资源任务。因此,当诸如更新列表,更改视图等操作要求您执行某些提取操作或更新操作时,您应该使用异步任务,以便可以将这些操作保持在UI线程之外,但请注意,这些操作仍以某种方式连接到UI 。
对于长时间运行的任务(不需要UI更新),您可以改用服务,因为即使没有UI也可以使用服务。
因此,对于短期任务,请使用异步任务,因为它们会在您的产卵活动死亡后被操作系统杀死(通常不会在操作中死亡,但会完成其任务)。对于冗长而重复的任务,请改用服务。
有关更多信息,请参见线程:
和
doInBackground
如果不使用进度条,长时间运行的功能将冻结屏幕。