AsyncTask
或Service
来完成相同的任务,但通常其中一个更适合该任务。
AsyncTask
用于一次性耗时任务,这些任务不能在UI线程上运行。常见示例是按下按钮时获取/处理数据。
Service
设计为在后台持续运行。在上面的示例中,当按下按钮时获取数据,您可以启动服务,让其获取数据,然后停止服务,但这是低效的。使用AsyncTask
会更快,它只运行一次,返回数据,然后就完成了。Service
是最好的选择。这包括播放音乐、不断检查新数据等示例。Service
适用于希望在应用程序的Activity
未打开时运行代码的情况。而AsyncTask
旨在使在UI线程之外执行代码变得非常简单。Service
是Android框架的组成部分之一,不需要UI执行。这意味着即使应用程序未被用户主动使用,也可以使用服务来执行某些操作。这并不意味着服务将在单独的线程中运行,而是在主线程中运行,当需要在单独的线程中执行操作时,可以在单独的线程中执行。
AsyncTask
则用于在单独的线程上执行阻塞UI任务。它就像创建一个新线程,并在处理创建和维护线程及发送结果到主线程的所有任务时执行任务的方式一样由AsyncTask处理。
示例用途包括在后台播放音乐,与服务器同步数据等无需用户交互的操作以及从服务器提取数据,CRUD操作等。
服务和异步任务几乎是在做同样的事情,几乎。使用服务或异步任务取决于您的要求。
例如,如果您想要在从服务器加载数据到列表视图后按下某个按钮或更改屏幕,最好使用异步任务。它与主UI线程并行运行(在后台运行)。对于运行异步任务的活动或应用程序,应该在主UI线程上。退出应用程序后没有异步任务。
但服务不是这样的,一旦启动服务,它可以在您退出应用程序后继续运行,除非您停止服务。就像我说的那样,这取决于您的要求。如果您想要持续检查数据接收或检查网络状态,最好使用服务。
愉快的编码。
将一个本地、进程内、基类服务✱与AsyncTask
进行比较:
✱(本答案不涉及导出的服务或在与客户端不同进程中运行的任何服务,因为期望的用例与AsyncTask
大不相同。此外,出于简洁起见,某些特定的Service
子类(例如IntentService
,JobService
)的性质将在此处被忽略。)
进程生命周期
Service
表示对操作系统的"应用程序希望执行长时间运行操作而不与用户进行交互" [ref]。
Service
时,Android会理解您不希望该进程被杀死。同样的情况也适用于当您有一个Activity
在屏幕上显示时,并且尤其适用于当您运行一个前台服务时。(当所有的应用组件都消失时,Android会认为:“哦,现在是一个好时机来杀掉这个应用程序,以便我可以释放资源”)。Service.onCreate()
的最后返回值,Android可以尝试“恢复”由于资源压力而被杀死的应用程序/服务[ref]。
AsyncTasks
并不会做任何这些事情。无论您有多少后台线程正在运行,或者它们正在努力工作的程度如何:Android都不会仅因为您的应用程序正在使用CPU而保持您的应用程序处于活动状态。它必须有一种方式来知道您的应用程序仍然有工作要做;这就是为什么Services
向操作系统注册,而AsyncTasks
则没有。
多线程
AsyncTasks
是关于创建一个后台线程来执行任务,并以线程安全的方式将结果呈现给UI线程。
每次新的AsyncTask
执行通常会导致更多的并发(更多的线程),但受到AsyncTasks
线程池的限制 [ref]。
另一方面,Service
方法总是在UI线程上调用[ref]。这适用于onCreate()
、onStartCommand()
、onDestroy()
、onServiceConnected()
等。因此,在某种意义上,Services
不会在后台“运行”。一旦它们启动(onCreate()
),它们只是“坐”在那里——直到需要清理、执行onStartCommand()
等操作。
Services
不会导致更多并发。由于它们运行在UI线程上,因此Service方法不是处理大量工作的好地方。Service
,添加自己的方法,并从任何线程调用它们。但如果这样做,线程安全的责任就在您身上,而不是框架。Service
中添加后台线程(或其他类型的工作程序),则可以自由地这样做。例如,您可以在Service.onCreate()
中启动后台线程/AsyncTask
。但并非所有用例都需要这样做。例如:
Service
运行,以便可以在“后台”(也就是说,没有任何屏幕上的 Activities
)继续获取位置更新。BroadcastReceiver
(在 API 26 之后,您不能总是通过清单来实现这一点,因此必须在运行时进行注册 [ref])。 这两种用例都不需要大量的 CPU 活动;它们只需要应用程序不被杀死即可。
作为 Workers
Services
不是面向任务的。它们不像 AsyncTasks
那样设置为“执行任务”和“传递结果”。Services
不解决任何线程安全问题(尽管所有方法都在单个线程上执行)。另一方面,AsyncTasks
可以处理这些复杂性。
AsyncTask
已被标记为弃用。但这并不意味着您应该用Services
替换AsyncTasks
!(如果您从这个答案中学到了任何东西,那么这一点应该很清楚。)
简而言之
Services
主要是为了“存在”。它们就像一个屏幕外的Activity
,提供了一个理由让应用程序保持活动状态,而其他组件负责执行“工作”。AsyncTasks
执行“工作”,但它们本身不会保持进程处于活动状态。