处理程序与AsyncTask


128

我对何时选择AsyncTask而不是Handler感到困惑。假设我有一些代码想每n秒运行一次,这将更新UI。我为什么要选择一个?


1
使用AsyncTaskLoaders变得更加复杂。有关更多信息,请参见stackoverflow.com/q/7120813/969325
Warpzit

Answers:


75

IMO,AsyncTask的编写目的是提供一种便捷,易于使用的方式来实现Android应用程序中的后台处理,而不必过多担心底层细节(线程,消息循环等)。它提供了回调方法,可帮助安排任务并在需要时轻松更新UI。

但是,必须注意,使用AsyncTask时,开发人员正在屈从于其局限性,这是由于该类作者做出的设计决定所致。例如,我最近发现使用AsyncTasks可以调度的作业数量有限制。

Handler对这两者更透明,并且可能会给您更多自由。因此,如果您想对事物进行更多控制,则可以选择Handler,否则AsynTask可以正常工作。


那就对了。我将AsyncTasks用于项目中的所有后台操作。从某个时候开始,我开始达到最大工作限制,所以我的任务只会在另一个任务完成之后才开始。最后,我不得不更改所有结构以停止使用asynctasks并避免达到该限制。
tbraun

5
从Honeycomb开始,AsyncTasks在一个线程上执行,因此不再有并行性。您仍然可以在并行Executor实现中运行它们。
Mrsnowflake 2013年

63

我的经验法则是:

  • 如果您要进行与UI相关的孤立操作,例如下载数据以显示在列表中,请继续使用AsyncTask

  • 如果您要执行多个重复任务,例如下载要在ImageViews下载时显示的多个图像(例如下载缩略图),请使用带有的任务队列Handler


处理程序位于API级别1和API级别3中的ASYNCTASK。是否会不建议您弃用?becaz专注于将应用程序从旧版本移植到2.2和2.3 ..
yokks 2011年

10
两者都不会很快被弃用。处理程序将永远不会被弃用,因为UI基本上是围绕它构建的。
alexanderblom

您是否不应该使用加载程序来加载要显示的UI数据?
nbarraille 2014年

19

始终尽量避免使用AsyncTask,主要是由于以下原因:

  • 由于系统设置了ThreadPool基数和最大大小,因此不能保证AsyncTask可以运行。如果创建的asynctask过多,它们最终将被销毁

  • AsyncTask甚至可以在运行时自动终止,具体取决于活动生命周期,您无法对其进行控制

  • 在UI线程上运行的AsyncTask方法(例如onPostExecute)可以在其所引用的活动(该活动不再可见)或可能处于不同的布局状态(例如更改方向)后执行。

总之,您不应该使用AsyncTask的UIThread链接方法,这是它的主要优点!!!此外,您只应在doInBackground上执行非关键性的工作。阅读此主题以获取有关此问题的更多见解:

AsyncTask在概念上确实存在缺陷吗?还是我只是想念一些东西?

总结一下,当上述任何问题可能引起您的关注时,请尝试使用IntentServices,HandlerThread或ThreadPoolExecutor而不是AsyncTask。当然,这将需要更多的工作,但您的应用程序将更安全。


是的,我花了很多时间后悔AsyncTasks的许多用法。他们看起来很棒,但是...这么多问题!
Scott Biggs 2015年

6
抱歉,我坚决反对您的观点,但我不能让您的拙劣风格对Android造成不利影响。要点一 您不应运行太多线程。如果遇到这种情况,您的体系结构就是foobar。第2点。地球上的事情..好的,是的,对于垃圾回收器,android中的所有内容都是免费游戏...在某些严格的任务滥用情况下,您只会看到如上所述的抽象行为。要点3。管理您的任务(不是无礼)是新手技能。您可以在调用onPause时将其杀死,或者适当地分离并相应地附加它。
StarWind0 '16

1
vogella.com/tutorials/AndroidBackgroundProcessing/article.html这就是您学习如何正确完成任务而没有上述问题的全部(假设您没有做几百个任务)
StarWind0,2016年

16

如果您想每x秒进行一次计算,则可能应该RunnableHandler(带有postDelayed())上安排一个,并且Runnable应该在当前UI线程中开始。如果要在另一个线程中启动它,请使用HandlerThread。AsyncTask对我们来说更易于使用,但没有比处理程序更好。


7

处理程序与应用程序的主线程关联。它处理和调度从后台线程发送到应用程序主线程的消息和可运行对象。

AsyncTask提供了一种简单的方法来处理后台线程,以便更新UI而不用耗时的操作阻止它。

答案是两者都可用于从后台线程更新UI,不同之处在于您的执行方案。您可以考虑使用处理程序来发布延迟的消息或以特定顺序将消息发送到MessageQueue。

如果您想以一种方便的方式在应用程序主线程和后台线程之间交换参数(从而更新UI),则可以考虑使用AsyncTask。


3
您可以创建自己的与另一个线程关联的处理程序。
Aleksejs Mjaliks 2012年

处理程序并不一定要绑定到主线程(UI线程)。它与实例化该线程的线程绑定,并处理到达此线程消息队列的Message或Runnable。它还可以将Message和Runnable对象发送到此线程消息队列。
azec-pdx 2014年

2

AsyncTask假定完成一些后台工作后,您将在UI线程上执行某些操作。另外,您只能执行一次(此后,其状态为,FINISHED并且将再次尝试再次执行它,您将获得异常)。而且,使用它的灵活性不高。是的,您可以使用THREAD_POOL_EXECUTOR并行执行,但是这样做可能不值得。

Handler除了处理Runnables和Messages之外,不假定任何内容。另外,它可以根据需要运行多次。您可以自由决定必须将其附加到哪个线程,如何与其他处理程序通信,或者使用来生成它们HandlerThread。因此,它更加灵活,适合重复工作。

在这里查看其他Handler示例。


0

他们是最好的面试问题。 AsyncTask-它们用于卸载UI线程并在后台执行任务。 处理程序 -Android主体具有UI和后台线程之间直接的通信方式。处理程序必须用于发送消息或可通过消息队列运行。

因此,AsyncTasks用于需要在后台执行任务的地方,而Handlers用于UI和Background Thread之间的通信。


0

doInBackground-基本上可以在另一个线程中工作。 onPostExecute-将结果发布到UI线程上,并且在内部将消息发送到主线程的处理程序。主UI线程已具有与它相关联的循环程序和处理程序。

因此,基本上,如果您必须执行一些后台任务,请使用AsyncTask。但是最终,如果需要在UI上进行某些更新,它将使用主线程的处理程序。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.