Android: AsyncTask vs Service



为什么我在大多数问题的答案中读到了很多关于AsyncTask和Loaders的内容,而没有关于Services的内容?服务只是不太为人所知,或者它们被弃用了,或者有一些不好的属性或其他什么?有什么不同?

(顺便说一下,我知道还有其他关于它的线程,但没有一个真正明确的区别,帮助开发人员容易地决定他是否更好地使用一个或另一个实际问题)

在某些情况下,有可能完成相同的任务与AsyncTaskService,但通常一个比另一个更适合的任务。

AsyncTask是为一次性的耗时任务而设计的,这些任务不能在UI线程中运行。一个常见的例子是在按下按钮时获取/处理数据。

Service s被设计为在后台持续运行。在上面的按钮被按下时获取数据的例子中,你可以启动一个服务,让它获取数据,然后停止它,但这是低效的。使用AsyncTask要快得多,它只运行一次,返回数据,然后就完成了。

如果你需要在后台持续做一些事情,那么Service是你最好的选择。这方面的例子包括播放音乐,不断检查新数据等。

而且,正如Sherif已经说过的,服务并不一定要在UI线程之外运行。

在大多数情况下,Service s适用于即使应用程序的Activity未打开也要运行代码的情况。AsyncTask的目的是使执行代码的UI线程非常简单。

服务是完全不同的:服务不是线程!

你的Activity绑定到一个服务,这个服务包含一些函数,当被调用时,会阻塞调用线程。您的服务可能用于将温度从摄氏度更改为摄氏度。任何绑定的活动都可以获得此服务。


然而,AsyncTask是一个线程,在后台做一些工作,同时有能力报告结果回调用线程。

只是一个想法:一个服务可能有一个 AsyncTask 对象!

Service是Android框架的组件之一,它不需要UI来执行,这意味着即使在应用程序不被用户积极使用的时候,你也可以用service来执行一些操作。这并不意味着服务将在一个单独的线程中运行,而是在主线程中运行,并且在需要时可以在一个单独的线程中执行操作。示例用法是在后台播放音乐,在后台与服务器同步数据而无需用户交互等

另一方面,

AsyncTask用于在单独的线程上执行UI阻塞任务。这就像创建一个新线程并执行任务一样,当创建和维护线程并将结果发送回主线程的所有任务都由AsyncTask负责时示例用法是从服务器获取数据,内容解析器上的CRUD操作等

Serviceasynctasks几乎做同样的事情,几乎。使用service还是asynctask取决于你的需求是什么。

作为一个例子,如果你想在点击一些按钮或改变屏幕后从服务器加载数据到listview,你最好使用asynctask。它与主UI线程并行运行(在后台运行)。运行asyncack活动或你的应用程序应该在主UI线程。退出应用程序后,没有asynctask。

但是服务不是这样的,一旦你启动了一个服务,它可以在你退出应用程序后运行,除非你停止了这个服务。就像我说的,这取决于你的要求。如果你想持续检查数据接收或持续检查网络状态,你最好选择service。

幸福的编码。

在少数情况下,您可以使用两者实现相同的功能。与异步任务不同,服务有自己的生命周期并继承上下文(服务比异步任务更健壮)。Service可以运行,即使你已经退出了应用程序。如果你想在应用程序关闭后做一些事情,并且还需要上下文变量,你可以选择Service。

示例:如果你想播放音乐,并且不想在用户离开应用程序时暂停,那么你肯定会选择Service。

本地、进程内、基类服务AsyncTask的译者比较:

译者(此答案不涉及导出服务,或任何在与客户端不同的进程中运行的服务,因为预期的用例与AsyncTask的用例有很大的不同。此外,为了简洁起见,某些特殊的Service子类(例如,IntentService, JobService)的性质在这里将被忽略。

流程生命周期

对于操作系统来说,Service表示"应用程序希望在不与用户交互的情况下执行长时间运行的操作"[ref]。

当你有一个Service运行时,Android明白你不希望你的进程被杀死。当您在屏幕上有Activity时也是如此,当您运行前台服务时尤其如此。(当你所有的应用程序组件消失时,Android会想:"哦,现在是时候关闭这个应用程序了,这样我就可以释放资源了。")

此外,根据Service.onCreate()的最后一个返回值,Android可以尝试"恢复"由于资源压力而被杀死的应用程序/服务[ref]。

AsyncTasks不要这样做。不管你有多少后台线程在运行,或者它们工作有多辛苦:Android不会仅仅因为你的应用在使用CPU就让你的应用保持活跃。它必须有办法让知道你的应用还有工作要做;这就是为什么Services在操作系统中注册,而AsyncTasks没有。

多线程

AsyncTasks都是关于创建一个后台线程来完成工作,然后以线程安全的方式将工作结果呈现给UI线程。

每次新的AsyncTask执行通常会导致更多的并发性(更多的线程),受AsyncTasks's线程池的限制[ref]。

另一方面,

Service方法总是在UI线程 [ref]上调用。这适用于onCreate(), onStartCommand(), onDestroy(), onServiceConnected()等。所以,在某种意义上,Services不会在后台"运行"。一旦它们启动(onCreate()),它们就会"坐在"那里——直到需要清理、执行onStartCommand()等。

换句话说,添加额外的Services并不会导致更多的并发性。服务方法不是做大量工作的好地方,因为它们在UI线程上运行。

当然,您可以扩展Service,添加您自己的方法,并从任何您想要的线程调用它们。但是,如果你这样做,线程安全的责任在于你——而不是框架。

如果你想添加一个后台线程(或其他类型的工作者)到你的Service,你可以自由地这样做。例如,您可以在Service.onCreate()中启动一个后台线程/AsyncTask。但是并不是所有的用例都需要这个。例如:

  • 你可能希望保持Service运行,这样你就可以继续在"后台"获得位置更新(意思是,不一定有任何Activities在屏幕上)。
  • 或者,你可能想让你的应用程序保持活跃,这样你就可以保持一个"隐式"的BroadcastReceiver长期注册(在API 26之后,你不能总是通过manifest来做到这一点,所以你必须在运行时注册而不是[ref])。

这些用例都不需要大量的CPU活动;它们只要求应用不能被杀死

作为工人

Services不是面向任务的。它们不像AsyncTasks那样"执行任务"one_answers"交付结果"。Services不解决任何线程安全问题(尽管事实上所有方法都在单个线程上执行)。另一方面,AsyncTasks为您处理这种复杂性。

请注意,AsyncTask已被指定为弃用。但这并不意味着你应该用Services代替AsyncTasks !(如果你从这个答案中学到了什么,那就很清楚了。)

TL;博士

Services大多是为了"存在"。它们就像一个屏幕外的Activity,为应用程序提供一个保持活力的理由,而其他组件则负责完成"工作"。AsyncTasks确实"工作",但它们本身不会使进程保持活力。

最新更新