Android平台中的Service vs IntentService

Posted

技术标签:

【中文标题】Android平台中的Service vs IntentService【英文标题】:Service vs IntentService in the Android platform 【发布时间】:2013-03-09 14:10:36 【问题描述】:

我正在寻找一个可以用IntentService 完成而不能用Service 完成的示例(反之亦然)?

我也相信IntentService 在不同的线程中运行,而Service 不会。因此,据我所知,在自己的线程中启动服务就像启动IntentService。对吗?

【问题讨论】:

IntentService is used for short tasks (etc) and a service is for long ones 你从哪里读到的? 另外,我建议您阅读 IntentService 的源代码。它非常清楚它是什么以及它的作用。 看到你的评论后,我编辑了我的问题。 IntentService 代码:android.googlesource.com/platform/frameworks/base/+/refs/heads/… 上一条评论中的链接(由 greg7gkb 撰写)非常适合阅读。 【参考方案1】:

Tejas Lagvankar 关于这个主题写了一篇很好的post。 以下是 Service 和 IntentService 之间的一些主要区别。

何时使用?

Service 可以在没有 UI 的任务中使用,但不能太长。如果需要执行较长的任务,则必须在 Service 中使用线程。

IntentService 可用于通常不与主线程通信的长任务。如果需要通信,可以使用主线程处理程序或广播意图。另一种使用情况是需要回调时(意图触发的任务)。

如何触发?

Service由调用方法startService()触发。

IntentService 使用 Intent 触发,它产生一个新的工作线程,并在该线程上调用方法 onHandleIntent()

触发自

ServiceIntentService 可以从任何线程、活动或其他应用程序组件触发。

运行时

Service 在后台运行,但在应用程序的主线程上运行。

IntentService 在单独的工作线程上运行。

限制/缺点

Service 可能会阻塞应用程序的主线程。

IntentService 无法并行运行任务。因此,所有连续的意图都将进入工作线程的消息队列并按顺序执行。

什么时候停止?

如果您实现了一个服务,您有责任在服务完成后停止服务,方法是调用stopSelf()stopService()。 (如果只想提供绑定,则不需要实现该方法)。

IntentService 在处理完所有启动请求后停止服务,因此您无需调用stopSelf()

【讨论】:

简短而甜蜜,但如果您编辑您的答案(包括 CommonsWare 的积分)会更好,因为很多人只阅读接受或最受好评的答案 @Darpan 服务是一个应用程序组件,可以在后台执行长时间运行的操作,不提供用户界面。服务在其托管进程的主线程中运行。服务不会创建自己的线程,也不会在单独的进程中运行(除非您另外指定)。这意味着,如果您的服务要执行任何 CPU 密集型工作或阻塞操作(例如 MP3 播放或网络),您应该在服务中创建一个新线程来完成这项工作。 "IntentService 必须从主线程触发。"你确定吗?在我的 MainActivity onCreate() 中,当我从新线程(下面的代码)调用 IntentService 时,它​​仍然对我有用。 new Thread(new Runnable() @Override public void run() Intent intent = new Intent(context, HelloIntentService.class); startService(intent); ).start(); @AshokBijoyDebnath 你是对的! ServicesIntentServices 可以从任何线程、活动或其他应用程序组件启动。我刚刚编辑了答案的文本来解决这个问题。感谢您的编辑建议! :) 没问题,加油!【参考方案2】:

如果有人可以向我展示一个可以用IntentService 完成而不能用Service 完成的示例,反之亦然。

根据定义,这是不可能的。 IntentServiceService 的子类,用 Java 编写。因此,IntentService 所做的任何事情,Service 都可以做,只要包含 IntentService 使用的相关代码位。

使用自己的线程启动服务就像启动 IntentService。不是吗?

IntentService 的三个主要特征是:

后台线程

Intents 的自动排队传递到onStartCommand(),所以如果一个Intent 正在后台线程上被onHandleIntent() 处理,其他命令排队等待轮到它们

一旦队列为空,通过调用stopSelf()自动关闭IntentService

所有这些都可以通过Service 实现,而无需扩展IntentService

【讨论】:

有点晚了,但我发现用startService 调用的Service 在抛出ANR 之前只能运行大约10 秒——IntentService 以广播意图开始不会好像有这个限制 @edthethird:那是因为您占用了主应用程序线程。所有组件上的所有生命周期方法,包括ServiceonStartCommand(),都在主应用程序线程上调用。您不能在不冻结 UI 的情况下占用该线程超过几毫秒,如果您花费很多秒,您将获得相当于 ANR 的服务。 是的,我评论得太早了。我正在做onStartCommand 而不是onHandleIntent 的工作——看起来onStartCommand 在UI 线程上运行,但是为onHandleIntent 执行生成了一个单独的线程。 @IgorGanapolsky: IntentServiceonHandleIntent() 返回后调用它自己,如果没有更多工作要做。 问题不是英语,而是编程。例如,“我已经关闭了应用程序”没有精确的定义,所以我无法告诉你发生这种情况时会发生什么。我也不知道“我已关闭应用程序”与“将在 1 小时后下载”有何关系。您可以考虑提出一个单独的 Stack Overflow 问题,您可以在其中提供“将在 1 小时后下载”的 minimal reproducible example。在那里,您可以详细说明“我已关闭应用”是什么意思(例如,用户具体做了什么来关闭应用?)。【参考方案3】:

服务

startService() 调用 从任何Thread 触发 在Main Thread 上运行 可能会阻塞主 (UI) 线程。始终在服务中使用线程来处理长任务 一旦任务完成,我们有责任通过调用stopSelf()stopService() 停止服务

IntentService

它执行长任务通常不与主线程通信,如果需要通信则由HandlerBroadcastReceiver完成 通过Intent调用 从Main Thread触发 在单独的线程上运行 无法并行运行任务,并且多个意图在同一个工作线程上排队。

【讨论】:

一个IntentService也可以被startService调用。请相应地编辑您的答案并使其连贯。【参考方案4】:

不要重新发明***

IntentService 扩展了Service 类,这显然意味着IntentService 是为了相同 目的而故意制作的。

那么目的是什么?

`IntentService 的目的是让我们的工作更轻松地运行后台任务,甚至不用担心

工作线程的创建

一一排队处理多请求(Threading

销毁Service

所以Service 可以完成IntentService 可以完成的任何任务。如果您的要求符合上述标准,那么您不必在Service 类中编写这些逻辑。 所以不要重新发明***,因为IntentService 是发明的***。

“主要”区别

Service 在 UI 线程上运行,而 IntentService 在 单独的线程

什么时候使用 IntentService?

当您想要一个一个地执行多个超出 Activity 范围的后台任务时,IntentService 是完美的选择。

IntentService 如何由Service 组成

普通服务在 UI 线程上运行(任何 Android 组件类型默认运行​​在 UI 线程上,例如 ActivityBroadcastReceiverContentProviderService)。如果您必须做一些可能需要一段时间才能完成的工作,那么您必须创建一个线程。在多个请求的情况下,您将不得不处理synchronizationIntentService 提供了一些默认实现,可以为您完成这些任务。 根据developer page

    IntentService 创建工作线程

    IntentService 创建一个工作队列,将请求一一发送到onHandleIntent() 方法

    当没有工作时,IntentService 调用 stopSelf() 方法 为空的onBind() 方法提供默认实现 onStartCommand() 的默认实现将 Intent 请求发送到 WorkQueue 并最终发送到 onHandleIntent()

【讨论】:

When you want to perform multiple background tasks one by one which exists beyond the scope of an Activity then the IntentService is perfect. ==> 你能举个例子吗? 从播放列表中一首一首下载歌曲。 @Wini【参考方案5】:

为已接受的答案加分:

查看 Android API 中 IntentService 的使用。 例如:

public class SimpleWakefulService extends IntentService 
    public SimpleWakefulService() 
        super("SimpleWakefulService");
    

    @Override
    protected void onHandleIntent(Intent intent)   ...

要为您的应用创建一个 IntentService 组件,请定义一个扩展 IntentService 的类,并在其中定义一个覆盖 onHandleIntent() 的方法。

另外,查看 IntentService 的源代码,它的构造函数和生命周期方法,如 onStartCommand...

  @Override
    public int More ...onStartCommand(Intent intent, int flags, int startId) 
       onStart(intent, startId);
        return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
    

AsyncTask 一起服务是许多人的最佳方法之一 有效载荷不大的用例。或者只是创建一个类 扩展 IntentService。安卓4.0起全网 操作应该在后台进程中,否则应用程序编译/构建失败。 与 UI 分离的线程。 AsyncTask 类提供了一种从 UI 线程触发新任务的最简单方法。有关此主题的更多讨论,请参阅博客文章

来自Android developers guide:

IntentService 是按需处理异步请求(表示为 Intent)的服务的基类。客户端通过 startService(Intent) 调用发送请求;该服务根据需要启动,依次使用工作线程处理每个 Intent,并在其工作结束时自行停止。

IntentService 中使用的设计模式

: 这种“工作队列处理器”模式通常用于从应用程序的主线程卸载任务。 IntentService 类的存在是为了简化这种模式并处理机制。要使用它,请扩展 IntentService 并实现 onHandleIntent(Intent)。 IntentService 将接收 Intent,启动工作线程,并根据需要停止服务。

所有请求都在单个工作线程上处理——它们可能需要尽可能长的时间(并且不会阻塞应用程序的主循环),但一次只会处理一个请求。

IntentService 类为在单个后台线程上运行操作提供了一个简单的结构。这允许它处理长时间运行的操作,而不会影响用户界面的响应能力。此外,IntentService 不受大多数​​用户界面生命周期事件的影响,因此它会在可能关闭 AsyncTask 的情况下继续运行。

IntentService 有一些限制:

它不能直接与您的用户界面交互。要将其结果放入 UI,您必须将它们发送到 Activity。 工作请求按顺序运行。如果一个操作正在 IntentService 中运行,并且您向它发送另一个请求,则该请求将一直等待,直到第一个操作完成。 在 IntentService 上运行的操作不能被中断。 但是,在大多数情况下

IntentService 是简单后台操作的首选方式

**

凌空图书馆

有一个库叫做volley-library for developing android networking applications 源代码在 GitHub 上面向公众开放。

Best practices for Background jobs的android官方文档: 有助于更好地理解意图服务、线程、处理程序、服务。还有Performing Network Operations

【讨论】:

如果你能给出简短的、中肯的答案可能会更好。【参考方案6】:

我相信你可以通过谷歌搜索诸如“Android IntentService vs Service”之类的东西来找到一个广泛的差异列表

每个示例的一个更重要的区别是 IntentService 在完成后自行结束。

一些例子(快速编造)可能是;

IntentService:如果您想在打开应用程序开始时下载一堆图像。这是一个一次性的过程,下载完所有内容后就可以自行清理。

服务:一种服务,将不断用于通过 Web API 调用在您的应用和后端之间进行通信。即使它完成了当前任务,您仍然希望它在几分钟后完成,以便进行更多交流。

【讨论】:

我没有找到一个可以用一个而不是另一个的例子。只是一些对我没有帮助的解释。 试试这个网站,它对基本的 Android 概念有很多很好的解释,并有很好的例子vogella.com/articles/AndroidServices/article.html 这是另一个“如何使用”的例子。不是在专门使用服务和意图服务时。请给我一个理论示例,而不是指向“如何使用”或该仪表的任何其他链接的链接。我不是要求你为我“工作”,而我什么都不做,只是我已经看到了所有这些喜欢但仍然不确定。 这是非常重要的区别。例如,如果您使用服务来保持与服务器的持久连接,则不能为此使用 intentservice,因为它在完成所有任务后立即终止 当我用谷歌搜索时,它把我带到了这里。现在我处于无限循环中。【参考方案7】:

意图服务

IntentService 在自己的线程上运行。 完成后它会自行停止。更像是一发不可收拾。 随后的呼叫将排队。适合排队通话。 如果需要,您还可以在 IntentService 中旋转多个线程 - 您可以使用 ThreadPoolExecutor 实现此目的。 我这么说是因为很多人问我“为什么要使用IntentService,因为它不支持并行执行”。 IntentService 只是一个线程。你可以在里面做任何你需要的事情——甚至可以旋转多个线程。唯一需要注意的是,IntentService 在您旋转这些多个线程后立即完成。它不会等待那些线程回来。你需要照顾好这个。所以我建议在这些情况下使用ThreadPoolExecutor

适合同步、上传等……

服务

默认情况下Service 在主线程上运行。您需要旋转一个工作线程来完成您的工作。 您需要明确停止service。 我将它用于当你需要在后台运行东西的情况下,即使你离开你的应用程序并返回更多的无头service

同样,如果需要,您可以运行多个线程。 可用于音乐播放器等应用。

如果需要,您可以随时使用BroadcastReceivers 与您的活动进行交流。

【讨论】:

【参考方案8】:

IntentService 是 Service 的扩展,用于简化需要在后台和单独线程中执行的任务的执行。

IntentService 启动,创建一个线程并在线程中运行它的任务。完成后,它会清理所有内容。一个 IntentService 只能同时运行一个实例,多个调用被排队。

它使用起来非常简单,对于很多用途都非常方便,例如下载东西。但它有一些限制,可能会让您想使用更基本(不简单)的服务。

例如,连接到 xmpp 服务器并由活动绑定的服务不能简单地使用 IntentService 完成。你最终会忽略或覆盖 IntentService 的东西。

【讨论】:

似乎大多数想要在后台运行真正长时间运行的服务的人最终都试图找到有关 IntentService 的信息,因为文档看起来好像是为了这样做,但你可以大多数情况下使用 new Thread(new Runnable()).start() 也一样好。换句话说,当它谈到“产生一个新线程”这就是它所做的一切时,它并没有将它移动到一个单独的进程,这实际上是大多数人想要分离时所做的事情一些正在运行的代码从 Activity 中出来!(因为只是产生 threads 无论如何都是单行) intentService 还负责线程的生命周期,并使用了一个looper,这有助于调度程序。它还确保只有一个实例正在运行,并将其他调用排队。【参考方案9】:

如果有人可以给我看一个例子,你可以用 IntentService 完成,而不能用 service 完成,反之亦然。

IntentService 不能用于长时间监听,就像 XMPP 监听器一样,它是一个单一的时间运算符,完成工作并挥手告别。

它也只有一个线程工作者,但有一个技巧,你可以无限使用它。

【讨论】:

【参考方案10】:

Android IntentService 与服务

1.服务

使用 startService() 调用服务。 可以从任何线程调用服务。 服务在主线程上运行后台操作 默认应用。因此,它可能会阻止您的应用程序的 UI。 多次调用的服务会创建多个实例。 需要使用 stopSelf() 或 stopService() 停止服务。 Android 服务可以运行并行操作。

2。意图服务

使用 Intent 调用 IntentService。 只能从主线程调用 IntentService。 IntentService 创建一个单独的工作线程来运行后台 操作。 多次调用的 IntentService 不会创建多个 实例。 IntentService 在队列完成后自动停止。不 需要触发 stopService() 或 stopSelf()。 在 IntentService 中,多个意图调用会自动排队 它们将按顺序执行。 IntentService 不能像服务一样运行并行操作。

参考Here

【讨论】:

【参考方案11】:

ServiceIntentService 之间的主要区别描述如下:

服务:

1.A Service 默认运行在应用程序的主线程上。(这里没有默认的工作线程可用)。所以用户需要创建一个单独的线程并在该线程中完成所需的工作。

2.一次允许多个请求。(多线程)

意图服务:

1.现在,来到IntentService,这里有一个默认工作线程可用于执行任何操作。 注意 - 您需要实现onHandleIntent() 方法,该方法接收每个启动请求的意图,您可以在其中进行后台工作。

2.但它一次只允许一个请求。

【讨论】:

以上是关于Android平台中的Service vs IntentService的主要内容,如果未能解决你的问题,请参考以下文章

Android平台调用Web Service:线程返回值

VS 2015 中的类库 - 构建跨平台库

Android service ( 二) 远程服务

Android平台调用Web Service:演示样例

JobDispacter vs Android-job(Evernote)

Android 原生应用 vs 跨平台应用