Asynctask vs 线程 vs 服务 vs 加载器
Posted
技术标签:
【中文标题】Asynctask vs 线程 vs 服务 vs 加载器【英文标题】:Asynctask vs Thread vs Services vs Loader 【发布时间】:2014-08-30 08:23:22 【问题描述】:我对 android 中 Asynctask
、Thread
、Service
、Loader
之间的区别感到有些困惑。
我知道它是如何工作的。但我仍然不明白我应该使用什么以及何时使用。
我在 Android 上工作了 3 年,并且通常仍将 AsyncTask
用于所有后台任务(有时是线程)。但是很多人说“Asynctask 已经过时”,不推荐使用。他们还建议使用 robospice 或 Volley。
那么,AsyncTask
真的那么糟糕,我应该使用框架来完成网络任务吗?我应该将什么用于后台(不是网络)任务?
【问题讨论】:
我使用一个执行器,来自 java 框架 相关线程 - Difference between Service, Async Task & Thread? 【参考方案1】:线程:与 Java 线程相同,使用它来执行繁重的操作,但您必须自己管理它,它还会导致同步问题,并且您无法从中更新 UI,直到您在 UI 线程上运行它.
AsyncTask:Android 中用于执行后台任务的出色线程库。它由 android 操作系统本身管理,您可以从中更新 UI。它可以并行或串行运行,具体取决于 android 的版本。有时在方向变化的情况下使用它可能会很麻烦,现在为了进行网络调用,您可以使用比AsyncTask
更好的 volley。 AsyncTasks 不关心他们的父活动是否正在运行,有时取消它可能非常乏味。所以,如果你使用 AsyncTask 来更好地调用其他 API,我建议你使用 RETROFIT 或 VOLLEY,如果你在两者之间选择 RETROFIT,我建议你看看 PICASSO 另一个很棒的来自 square 的库用于图像加载。
服务:要执行长期后台任务,您应该使用服务。如果需要,您可以将服务绑定到您的活动。您可以定义它们在同一个线程或不同线程中运行,并且您需要在清单中声明它,或者您可以使用IntentService
- 一种在自己的线程中运行的服务变体,但在使用它之前要小心,不要将它用于长时间运行的任务。这是一个单一的时间运算符。如果您要使用服务,请评估哪种情况更适合您的要求,使用普通服务或 IntentService
Loaders:这在很多方面与AsyncTask
相同,建议使用带有片段的loaders,它解决了异步任务的方向问题。
如果您已经迁移到 kotlin,我建议您查看 Coroutines。这些非常轻量级且对线程非常有效,并为您提供了对生命周期的大量控制。 我希望这会有所帮助。
【讨论】:
【参考方案2】:AysncTask 并不像 不完整那样“过时”。 除其他事项外,异步任务不会打扰其父活动当前是否正在运行。出于同样的原因,您包括检查以验证上下文是否为空。此外,除非您使用自己的线程池执行器,否则这些任务会串行执行。
Volley 试图填补这些空白,主要涉及与主线程和线程池同步。如果您想做需要平均网络请求的事情,它会表现得最佳;像一些元数据列表和图像(图片 youtube 应用程序请求和 facebook 应用程序请求的帖子)。
Volley 的典型优势如下:
-
它让工作线程了解活动(主线程)
您可以为下载请求提供更轻松的资源优先级。
一个典型的场景是您优先考虑文本而不是图像。
有效的请求缓存和内存管理。
可扩展
它为您提供了一个选项,可以在您的活动被关闭或重新启动时放弃您的请求。
与 AsyncTask 相比,数据检索模式更简单。
在 Google I/O 上提到的流式传输请求/视频方面,Volley 表现不佳。
我并不完全了解 robospice。 ps:如果你手头有时间看https://www.youtube.com/watch?v=yhv8l9F44qo
如果您希望进入其他具有相同基准的库,请阅读此处进一步阅读。 Comparison of Android networking libraries: OkHTTP, Retrofit, and Volley
【讨论】:
【参考方案3】:你使用什么抽象并不重要,它归结为Thread
。因此,Android 的每个异步/并行类都在幕后使用Thread
/Executor
,并且具有与线程完全相同的潜在问题,例如锁定。
then 的区别在于它的用法。例如,AsyncTask
定义了一个方便的完成回调 - onPostExecute()
。 CountDownTimer
可以让你控制时间等等。
您当然可以使用普通的Thread
,但在这种情况下,您必须投入更多时间来自己发现可能出现的问题。
因此,Android 为您提供了一些适合工作的工具。
【讨论】:
【参考方案4】:但是很多人说“Asynctask 已经过时”,不推荐使用。
我没有遇到过这样说的人。但决定框架的某些部分何时过时或弃用是 Android 团队的工作。 CursorLoaders
使用 AsyncTaskLoader
,它使用 AsyncTask
。 AsyncTasks
是一种抽象,可防止开发人员不得不实现讨厌的 Thread
状态逻辑。这意味着所有这些类在后台依次使用 useThreads
。
那么,Asynctask 真的那么糟糕吗?我应该使用框架 网络任务?我应该用什么作为背景(不是 网络)任务?
关键在于了解何时以及如何使用您的工具。你提到CursorLoader
。在这种特殊情况下,当您阅读文档并稍微使用它时,您会意识到它故意与ContentProviders
平滑集成。现在,ContentProviders
抽象底层数据;您可以查询本地 SQLite 数据库或远程服务器。
通常,AsyncTasks
用于检索简洁的“不太大”信息片段(用于与服务器通信时)。人们可能会说AsyncTasks
已经过时了,因为有更好(更高效)的方式与服务器交互(参见Retrofit
)。
【讨论】:
【参考方案5】:我认为AsyncTask
比Thread
更好,因为它在主线程上提供回调。 Loader
比 AsyncTask
更好,因为它还为您处理配置更改。
【讨论】:
【参考方案6】:AsyncTask:
AsyncTask 允许正确且轻松地使用 UI 线程。此类允许您执行后台操作并在 UI 线程上发布结果,而无需操作线程和/或处理程序。
AsyncTask
被设计为围绕 Thread 和 Handler 的辅助类,并不构成通用的线程框架。 AsyncTasks
最好用于短时间操作(最多几秒钟。)
如果您需要保持线程长时间运行,强烈建议您使用java.util.concurrent
包提供的各种API,例如Executor
、ThreadPoolExecutor
和FutureTask
。
Thread:
从主线程中移动大量或较长的任务,以便它们不会影响流畅的渲染和对用户输入的快速响应,这是您在应用中采用线程的最大原因。
使用它将长时间运行的计算与主线程(UI 线程)分开
Service:
Service 是一个应用程序组件,可以在后台执行长时间运行的操作,它不提供用户界面。
服务可以在后台处理网络事务、播放音乐、执行文件 I/O 或与内容提供者交互。
IntentService:
IntentService 是按需处理异步请求(表示为 Intent)的服务的基类。
所有请求都在单个工作线程上处理——它们可能需要尽可能长的时间(并且不会阻塞应用程序的主循环),但一次只会处理一个请求。
Loader:
Loader API 允许您从内容提供者或其他数据源加载数据,以便在 Activity 或 Fragment 中显示。
装载机解决了这些问题并带来了其他好处。例如:
加载程序在单独的线程上运行,以防止 UI 出现卡顿或无响应。
加载器通过在事件发生时提供回调方法来简化线程管理。
加载程序会在配置更改时保持并缓存结果,以防止重复查询。 加载器可以实现一个观察者来监控底层数据源的变化那么,Asynctask 真的那么糟糕,我应该使用框架来完成网络任务吗?我应该将什么用于后台(不是网络)任务?
使用AsyncTask
处理持续时间短于 5 毫秒的工作项。后台任务可以使用Thread
或Service
或IntentService
。
【讨论】:
以上是关于Asynctask vs 线程 vs 服务 vs 加载器的主要内容,如果未能解决你的问题,请参考以下文章
用于从 BlockingCollection 消费的计时器 vs 线程 vs RegisteredWaitHandle
异步方法中的 Await vs Task.Result [重复]