我应该为我的应用程序使用 AsyncTask 还是 IntentService?

Posted

技术标签:

【中文标题】我应该为我的应用程序使用 AsyncTask 还是 IntentService?【英文标题】:Should I use AsyncTask or IntentService for my application? 【发布时间】:2013-02-16 12:14:43 【问题描述】:

我一直在阅读有关与 android 的互联网连接的信息,并注意到有不同的方法来处理这个问题,即 AsyncTaskIntentService。但是,我仍然不确定要使用哪一个。我的应用程序基本上是一个带有谷歌地图的位置/路径查找器。我的互联网连接将用于在地图的某个半径范围内查找最近的路径。因此,每次用户将地图移动或滑动到新位置时,它都会更新最近的路线。它还将添加一条新路径,并允许用户对路径进行评分。

AsyncTask 是否足够,或者我应该使用IntentService

【问题讨论】:

【参考方案1】:

它们可以用于不同的目的。

AsyncTask 是一个方便的线程实用程序,如果您需要不断地告诉用户某事或定期在主线程上执行操作,可以使用它。它提供了很多细粒度的控制,并且由于它的性质,在Activity 中很容易使用,而IntentService 通常需要使用BroadcastReceiverIBinder 框架。

IntentService 可以像AsyncTask 一样使用,但它的目的是用于后台下载、上传或其他不需要用户交互或主线程的阻塞操作。例如,如果您想下载和缓存地图,您可能需要调用IntentService,这样用户就不必查看应用程序即可下载。同样,如果您将数据发送到您的服务器,IntentService 在这方面非常有帮助,因为您可以开始并忘记。例如,用户可以在您的应用中输入评论,然后按“发送”。 “发送”将启动IntentService,它会获取评论并将其发送到后台线程上的服务器。用户可以按“发送”并立即离开应用程序,评论最终仍会到达您的服务器(当然假设没有错误)。另一方面,如果您在 Activity 中使用 AsyncTask 执行此操作,则系统可能会在您的交换过程中终止您的进程,并且它可能会或可能不会通过。

一般来说,两者都不适用于长时间运行的应用程序。它们适用于简短的一次性操作。它们可用于永久或长期运行的操作,但不建议这样做。

【讨论】:

对于长时间运行的操作应该使用什么比? 通用 Java 线程(如果它是阻塞的)。您可以根据需要将其放入 Activity 或 Service 中。使用生命周期方法控制生命周期,以确保它们不会在不应该运行的时候运行。 -1: ...An IntentService generally requires manipulating the BroadcastReceiver framework. 不,它没有。请看@Joe Malin 的回答:***.com/a/15168625/109941? 这意味着与使用回调的 Asynctask 相比。您不必为任何事情使用 BroadcastReceivers,但如果您希望它向 Activity 报告,这是一种方法。另一种方法是绑定,因为它的核心是普通服务。 可以使用 IntentService 进行长时间运行的操作。我将它(正确)用于永久操作。【参考方案2】:

您应该使用AsyncTask 来处理与活动紧密相关的简短重复性任务,例如您当前正在尝试执行的操作。 IntentService 更适合应在后台运行的计划任务(重复或不重复),与您的活动无关。

【讨论】:

感谢您的回答。你能给我一个使用 IntentService 的任务示例吗? 假设您在应用程序中保存了给定区域的路线(如“收藏夹”或类似内容)。如果您想让它们保持最新状态,那么只需设置一个每天运行的 IntentService 并检查这些区域的更改。 啊,我明白了。所以我猜这就像我们手机上的 Facebook 或 Gmail 通知? 差不多,虽然我相当肯定那些使用推送通知,这是完全不同的事情。这就像使用 IMAP/POP3 的电子邮件应用程序,每 x 分钟检查一次电子邮件。 评论说:“IntentService 更适合于应该在后台运行的计划任务(重复或不重复),与您的活动无关。”但是如果你的应用程序没有运行,IntentService 就无法运行,如果你想在应用程序关闭的情况下运行某些东西,你需要的是 Service,而不是 IntentService。【参考方案3】:

AsyncTask 不能很好地配合配置更改或其他重启 Activity 的事情。

IntentService 适用于应该始终可用的东西,不管它需要多长时间才能完成它的工作。在大多数情况下,我更喜欢 IntentService,因为 AsyncTask 更加依赖于 Activity 状态。

一些注意事项:

AsyncTask 是最好的用于应该直接返回 UI 的快速任务,但它可以在各种情况下使用。 “定期在主线程上执行操作”的说法含糊不清。 AsyncTask 生成一个与主线程不同的新后台线程,并在新线程上工作。因此名称为 AsyncTask。 IntentService 不需要“操作”BroadcastReceiver 框架。您需要做的就是发送一个本地广播 Intent,并在您的 Activity 中检测它。我不知道这是否比 AsyncTask 更难。 IntentService 旨在执行长时间运行的任务,它在后台执行。 AsyncTaskLoader 可以使用,但它应该是 CursorLoader 等的基类。 如果您想在用户移动到新位置时刷新“附近”路径,IntentService 可能会更好。

在尝试更新位置之前不要忘记检查连接。

【讨论】:

【参考方案4】:

AsyncTask 与 Activity 的绑定非常紧密,如果您离开创建 AsyncTask 的 Activity,通常会导致泄漏窗口错误。但它们非常适合显示 ProgressBar,因为您可以快速更新进度百分比。

IntentService 更清洁、更安全。当您是初学者 Android 开发人员时,它们更难实现,但是一旦您学会了如何启动和处理它们,您可能永远不会回到 AsyncTasks!

IntentServices 还允许在您的应用中进行更加模块化的设计。我通常为我的所有 IntentServices 创建一个单独的类,但对于 AsyncTasks 我将它们创建为一个 Activity 内部类。如果要从 Activity 中分离出 AsyncTask,则必须在 AsyncTask 构造函数中传入 Activity Context 和 View 对象,这可能会很混乱。

【讨论】:

为了克服混乱的问题,你不能在你的 AsyncTask 类中添加一个内部接口吗?该接口将包含要实现的活动的回调方法?【参考方案5】:

如上所述AsyncTask 将解决您的问题。

但请记住,AsyncTask 有一个重要的弱点:它不能很好地处理Activity “刷新”(例如在旋转期间)。例如,如果用户在您的 AsyncTask 仍在加载内容时旋转手机,则可能会出现问题。如果这对你来说确实是个问题,我推荐AsyncTaskLoader

http://developer.android.com/reference/android/content/AsyncTaskLoader.html

【讨论】:

【参考方案6】:

AsyncTaskIntentService 有很多相同的

可以在工作线程中执行任务 可以在后台运行 继续运行直到任务完成事件启动它的活动被销毁 可以在任务运行期间或任务完成后通知更新 UI 对于AsyncTask,我们经常使用onProgressUpdateonPostExecute,或者如果您愿意,可以使用BroadcastReceiver 对于IntentService,我们使用BroadcastReceiver

不同

1) 在运行时或运行完成后发送任务

例如我们有一个任务:从fileName的服务器下载文件。

使用 AsyncTask

如果我们是AsyncTask的一个实例,在执行下载文件A期间,我们不能执行下载文件BAsyncTask(因为我们得到java.lang.IllegalStateException: Cannot execute task: the task is already running.)。同样在下载文件A完成后,我们无法执行下载文件B(因为我们得到java.lang.IllegalStateException: Cannot execute task: the task has already been executed (a task can be executed only once). 要在下载文件 A 期间或之后下载文件 B,我们需要创建 AsyncTask 的新实例。 => 要下载文件 A 和文件 B,我们需要 2 个 AsyncTask 实例 => 创建 2 个工作线程

使用 IntentService

在下载文件 A 期间,我们可以发送下载文件 B 的意图 => 下载文件 A 完成后将自动开始下载文件 B => 不需要新实例,不需要新的工作线程。

如果我们下载文件 A 完成后发送了下载文件 B 的意图?下载文件 A 完成后,IntentSevice 将被销毁(因为没有更多的任务)。因此,当开始下载文件 B 时,会创建 Service 的新实例,但没有创建新线程(服务仅使用 1 个工作线程,其名称在 IntentSevice 构造函数中定义

2) 实现AsyncTaskIntentService 更容易

正在使用 我们会看到AsyncTaskIntentService 有很多相同的,所以在大多数情况下我们可以使用AsyncTaskIntentService。不过

我经常将AsyncTask 用于一些在 1 Activity 中开始、完成、与 UI 交互的任务 我经常将IntentService 用于可以开始/完成和交互或不与任何Activity 的UI 交互的任务

这个答案是基于我的测试。如果我错了,请纠正我。希望对您有所帮助。

【讨论】:

【参考方案7】:

简而言之,AsyncTask 适用于必须与主线程通信的短任务。 IntentService 适用于不需要与主线程通信的长任务。

有关更多信息,请查看这些链接

http://www.onsandroid.com/2011/12/difference-between-android.html

https://medium.com/@skidanolegs/asynctask-vs-intentservice-1-example-without-code-5250bea6bdae

https://android.jlelse.eu/using-intentservice-vs-asynctask-in-android-2fec1b853ff4

【讨论】:

【参考方案8】:

我同意@DeeV 和@ebarrenechea 关于 Intent 服务的部分观点,您应该将其用于与 Activity 不紧密绑定的任务,例如将一些数据上传到服务器或将数据从服务器存储到数据库。

但从 Android 3.0 开始,引入了 Loaders API,它应该取代 AsyncTask。因此,例如对于应该在 Activity 中显示的加载列表,最好使用旨在处理所有配置更改和 Activity 生命周期的 Loader。

Vogella loader tutorial

【讨论】:

你确定Loader应该用于服务器工作吗?我以前从未听说过,而且我在您链接到的文档或教程中也没有看到任何建议。

以上是关于我应该为我的应用程序使用 AsyncTask 还是 IntentService?的主要内容,如果未能解决你的问题,请参考以下文章

我应该为我的 Rails 应用程序使用 Apache 还是 Nginx &Passenger 或 Mongrel

我应该如何实现我的 AsyncTask 类?

我应该为我的音频项目使用 DirectSound 还是 WASAPI?

我应该为我的电子商务网站使用 JWT 还是 Sessions?

不间断运行服务 - Thread,AsyncTask还是Executor?

要使用 AsyncTask 还是 Service?