我应该为我的应用程序使用 AsyncTask 还是 IntentService?
Posted
技术标签:
【中文标题】我应该为我的应用程序使用 AsyncTask 还是 IntentService?【英文标题】:Should I use AsyncTask or IntentService for my application? 【发布时间】:2013-02-16 12:14:43 【问题描述】:我一直在阅读有关与 android 的互联网连接的信息,并注意到有不同的方法来处理这个问题,即 AsyncTask
和 IntentService
。但是,我仍然不确定要使用哪一个。我的应用程序基本上是一个带有谷歌地图的位置/路径查找器。我的互联网连接将用于在地图的某个半径范围内查找最近的路径。因此,每次用户将地图移动或滑动到新位置时,它都会更新最近的路线。它还将添加一条新路径,并允许用户对路径进行评分。
AsyncTask
是否足够,或者我应该使用IntentService
?
【问题讨论】:
【参考方案1】:它们可以用于不同的目的。
AsyncTask
是一个方便的线程实用程序,如果您需要不断地告诉用户某事或定期在主线程上执行操作,可以使用它。它提供了很多细粒度的控制,并且由于它的性质,在Activity
中很容易使用,而IntentService
通常需要使用BroadcastReceiver
或IBinder
框架。
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】:AsyncTask
和IntentService
有很多相同的
AsyncTask
,我们经常使用onProgressUpdate
、onPostExecute
,或者如果您愿意,可以使用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) 实现AsyncTask
比IntentService
更容易
正在使用
我们会看到AsyncTask
和IntentService
有很多相同的,所以在大多数情况下我们可以使用AsyncTask
或IntentService
。不过
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
我应该为我的音频项目使用 DirectSound 还是 WASAPI?
我应该为我的电子商务网站使用 JWT 还是 Sessions?