【问题标题】:Android: AsyncTask vs ServiceAndroid:异步任务与服务
【发布时间】:2016-11-23 07:57:21
【问题描述】:

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

(顺便说一句,我知道还有其他关于它的线程,但没有一个真正说明明确的差异,可以帮助开发人员轻松决定他是否更好地使用一个或另一个来解决实际问题。)

【问题讨论】:

    标签: android


    【解决方案1】:

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

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

    Services 被设计为在后台持续运行。在上面按下按钮时获取数据的示例中,您可以启动一个服务,让它获取数据,然后停止它,但这效率低下。使用将运行一次、返回数据并完成的 AsyncTask 会快得多。

    不过,如果您需要在后台持续执行某项操作,Service 是您的最佳选择。这方面的示例包括播放音乐、不断检查新数据等。

    此外,正如 Sherif 已经说过的,服务不一定会在 UI 线程之外运行。

    在大多数情况下,Services 用于当您想要运行代码时,即使您的应用程序的Activity 未打开。 AsyncTasks 旨在使从 UI 线程执行代码变得异常简单。

    【讨论】:

    • 有趣的是,在 2010 年 Google I/O 的这次演讲中youtube.com/watch?v=xHXn3Kg2IQE,演讲者提供了 3 种不同的方法来从 REST API 获取数据,第一种方法使用服务。我不是 Android 专家,但我也觉得 Computerish 所说的基本正确。
    • 最后一段,“服务适用于当你想要运行代码时,即使你的应用程序的活动没有打开”。 AsyncTask 或后台线程也是如此。即当您按下您的活动或调用完成()并且您的活动不可见时,但您的后台线程仍在执行,直到您终止您的应用程序进程(例如通过从最近的任务交换)。我已经用 4.4.2 Google Nexus AOSP grouper 进行了检查
    • 但是,如果启动它的 Activity 在 AsyncTask 仍在运行时被杀死并且需要在完成后更新 UI 时,AsyncTask 可能会很棘手......(由于 Activity 已经被销毁,这将不起作用)。为什么不使用不需要手动停止的 IntentService,因为它一旦完成就会结束?
    • 伟大的点。关于服务的良好解释。即使工作完成,服务也会在后台持续运行。
    • @LarsH 如果我错了,请纠正我,但我认为您可以在 Activity/Fragment 中使用 BroadcastReceiver ,并在完成后从 IntentService 触发广播。因为您可以在重新创建活动/片段时重新注册广播,这应该涵盖您。另一种选择是使用 EventBus 来更新 UI(尽管我尽量避免这些 - 使代码更难遵循 imo)。
    【解决方案2】:

    Services 完全不同:服务不是线程

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


    但是AsyncTask 是一个在后台执行一些工作的线程,同时能够将结果报告回调用线程。

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

    【讨论】:

    • 服务被描述为在后台运行,即使在您的应用程序关闭时也会继续运行。 AsyncTask 也用于在后台做一些事情。明白我的意思吗?
    • 是的,但服务可能会或可能不会做某事。它们是一个持久的对象
    • "一个服务可能有一个 AsyncTask 对象!"感谢您指出了这一点。但这是一个好主意吗?这是您推荐的吗?还是在服务中使用更基本的线程技术会更好?
    • “您的活动绑定到服务”不一定。
    • @JacksOnF1re 我知道这就像我第一次开始编码时一样:p 但是“您的活动绑定到服务”是一个真实的陈述。我也可以绑定到这个服务。冰箱也可以绑定。这不会使声明无效..无论如何jk
    【解决方案3】:

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

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

    【讨论】:

    • 你能具体说明为什么你认为你的回答对问题有任何帮助吗?
    • 其他答案要么太短,要么太长,初学者无法理解。所以我用简单的话用例子准确地回答了
    【解决方案4】:

    Serviceasynctasks 几乎在做同样的事情,几乎。使用 service 或 asynctask 取决于您的要求。

    例如,如果您想在点击某个按钮或更改屏幕后将数据从服务器加载到列表视图,您最好使用 asynctask。它与主 ui 线程并行运行(在后台运行)。对于运行 asynctack 活动或您的应用程序应该在主 UI 线程上。从应用程序退出后没有异步任务。

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

    快乐的编码。

    【讨论】:

    • 您好 Ashana,我能问一下您为什么对已经回答的问题提供此答案吗?您对现有的标记答案不满意吗?或者您是否尝试通过对您有话要说的所有问题写下您的意见来建立一个 SO 档案?还是完全不同的东西?想不通,但我最近经常看到这种模式。
    • 是的,我知道答案已经给出,如果我在这里给出正确的答案或我的意见,我在这里看不到什么问题兄弟?因为您不是唯一一个寻找同一问题答案的人,如果有人难以理解上述答案中的解决方案,他/她可以向下滚动以寻找适合他们的答案,轻松理解一个。就是这样。感谢您的评论兄弟,我不是编程方面的天才或专业人士,只是想帮助别人,尝试教别人我已经知道的东西:)
    【解决方案5】:

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

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

    【讨论】:

      【解决方案6】:

      本地、进程内、基类服务✱与AsyncTask的比较:

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

      进程生命周期

      对于操作系统,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 为您处理这种复杂性。

      请注意,AsyncTaskslated for deprecation。但这并不意味着你应该用Services 替换你的AsyncTasks! (如果您从这个答案中学到了什么,那应该很清楚了。)

      TL;DR

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-11-14
        • 1970-01-01
        • 1970-01-01
        • 2018-07-01
        • 1970-01-01
        相关资源
        最近更新 更多