【发布时间】:2016-11-23 07:57:21
【问题描述】:
为什么我在大多数问题的答案中阅读了很多关于 AsyncTask 和 Loaders 的内容,而没有看到关于 Services 的内容?服务是否只是不太为人所知,或者它们是否已被弃用或有一些不好的属性或什么?有什么区别?
(顺便说一句,我知道还有其他关于它的线程,但没有一个真正说明明确的差异,可以帮助开发人员轻松决定他是否更好地使用一个或另一个来解决实际问题。)
【问题讨论】:
标签: android
为什么我在大多数问题的答案中阅读了很多关于 AsyncTask 和 Loaders 的内容,而没有看到关于 Services 的内容?服务是否只是不太为人所知,或者它们是否已被弃用或有一些不好的属性或什么?有什么区别?
(顺便说一句,我知道还有其他关于它的线程,但没有一个真正说明明确的差异,可以帮助开发人员轻松决定他是否更好地使用一个或另一个来解决实际问题。)
【问题讨论】:
标签: android
在某些情况下,可以使用AsyncTask 或Service 完成相同的任务,但通常一个比另一个更适合完成任务。
AsyncTasks 专为一次性的耗时任务而设计,这些任务无法在 UI 线程中运行。一个常见的例子是在按下按钮时获取/处理数据。
Services 被设计为在后台持续运行。在上面按下按钮时获取数据的示例中,您可以启动一个服务,让它获取数据,然后停止它,但这效率低下。使用将运行一次、返回数据并完成的 AsyncTask 会快得多。
不过,如果您需要在后台持续执行某项操作,Service 是您的最佳选择。这方面的示例包括播放音乐、不断检查新数据等。
此外,正如 Sherif 已经说过的,服务不一定会在 UI 线程之外运行。
在大多数情况下,Services 用于当您想要运行代码时,即使您的应用程序的Activity 未打开。 AsyncTasks 旨在使从 UI 线程执行代码变得异常简单。
【讨论】:
【讨论】:
Service是Android框架的组件之一,它不需要UI来执行,这意味着即使应用程序没有被用户主动使用,你也可以通过服务进行一些操作。这并不意味着服务将在单独的线程中运行,而是在主线程中运行,并且可以在需要时在单独的线程中执行操作。
示例用法是在后台播放音乐,在后台与服务器同步数据而无需用户交互等
另一方面,AsyncTask 用于在单独的线程上执行 UI 阻塞任务。当创建和维护线程并将结果发送回主线程的所有任务都由 AsyncTask 处理时,就像创建一个新线程并执行任务一样
示例用法是从服务器获取数据、内容解析器上的 CRUD 操作等
【讨论】:
Service 和 asynctasks 几乎在做同样的事情,几乎。使用 service 或 asynctask 取决于您的要求。
例如,如果您想在点击某个按钮或更改屏幕后将数据从服务器加载到列表视图,您最好使用 asynctask。它与主 ui 线程并行运行(在后台运行)。对于运行 asynctack 活动或您的应用程序应该在主 UI 线程上。从应用程序退出后没有异步任务。
但是服务不是这样的,一旦您启动服务,它可以在您退出应用程序后运行,除非您停止服务。就像我说的那样,这取决于您的要求。如果您想继续检查数据接收或持续检查网络状态,您最好使用服务。
快乐的编码。
【讨论】:
在少数情况下,您可以同时使用两者来实现相同的功能。与异步任务不同,服务有自己的生命周期并继承上下文(服务比异步任务更健壮)。即使您已退出应用程序,服务也可以运行。如果你想在应用关闭后做某事并且还需要上下文变量,你会去服务。
示例:如果您想播放音乐并且不想在用户离开应用时暂停,那么您肯定会选择 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 之后,您不能总是通过清单做到这一点,所以您必须在运行时注册而不是 [ref])。 这些用例都不需要大量的 CPU 活动;他们只是要求应用程序不要被杀死。
作为工人
Services 不是面向任务的。它们不是为了“执行任务”和“交付结果”而设置的,就像AsyncTasks 一样。 Services 不解决任何线程安全问题(尽管所有方法都在单个线程上执行)。另一方面,AsyncTasks 为您处理这种复杂性。
请注意,AsyncTask 是 slated for deprecation。但这并不意味着你应该用Services 替换你的AsyncTasks! (如果您从这个答案中学到了什么,那应该很清楚了。)
TL;DR
Services 主要是为了“存在”。它们就像一个屏幕外的Activity,为应用程序提供了一个保持活力的理由,而其他组件则负责完成“工作”。 AsyncTasks 做“工作”,但他们本身不会让进程保持活力。
【讨论】: