我对Android中Asynctask
,Thread
,Service
,Loader
之间的差异感到有些困惑。
我知道它是如何运作的。但我仍然不明白我应该使用什么以及何时使用。
我使用Android工作了3年,并且通常仍然使用AsyncTask
来执行所有后台任务(有时候是Thread)。但很多人都说'Asynctask已经过时了'#34;并且不建议使用它们。他们也建议使用robospice或Volley。
那么,AsyncTask
真的如此糟糕,我应该使用框架进行网络任务吗?我应该将什么用于后台(而不是网络)任务?
答案 0 :(得分:25)
线程:与Java线程相同,使用它来执行繁重的操作但是你必须自己管理它,它也可能导致同步问题,你不能从它更新UI,直到你在它上面运行它UI线程。
AsyncTask:Android中可用于执行后台任务的强大线程库。它由Android操作系统本身管理,您可以从中更新UI。它根据android的版本并行或串行运行。在方向更改的情况下,有时使用它可能会很麻烦,现在为了进行网络调用,您可以使用优于AsyncTask
的排球。 AsyncTasks不关心他们的父活动是否正在运行,有时取消它可能会非常繁琐。所以,如果您使用AsyncTask进行休息API调用,请更好地使用RETROFIT或VOLLEY,如果您选择两者之间的RETROFIT,我建议您查看{{3}来自广场的另一个令人敬畏的图像用于图像加载。
服务:对于长期后台任务,您应该使用服务。如果需要,您可以将服务绑定到您的活动。您可以定义它们在同一个线程或不同的线程中运行,您需要在清单中声明它,或者您可以使用IntentService
- 一个服务的变体,它在自己的线程中运行但在使用之前要小心,不要#39; t用于长时间运行的任务。它是一次性操作员。如果您打算使用服务,请评估适合您要求的情况,更好的是正常服务或IntentService
加载器:这在很多方面与AsyncTask
相同,建议使用带有碎片的加载器,它解决了asynctasks的方向问题。
如果您已经转移到kotlin,我建议您查看PICASSO。这些非常轻量级,对线程非常有效,并为您提供对生命周期的大量控制。 我希望这会有所帮助。
答案 1 :(得分:19)
AysncTasks并非“过时”,因为它们不完整。 除其他事项外,如果父活动当前正在运行,则异步任务不会受到影响。出于同样的原因,您可以包含检查以验证上下文是否为空。此外,除非您使用自己的线程池执行程序,否则这些任务将以串行方式执行。
Volley试图填补这些空白,主要是关于与主线程和线程池的同步。如果您希望执行需要平均网络请求的内容,它会表现得最佳;比如一些元数据列表和图像(图片是youtube app请求和facebook app发帖的请求)。
Volley的一些优点通常如下
我并不完全了解robospice。 Ps:如果你有时间,请看https://www.youtube.com/watch?v=yhv8l9F44qo
如果您希望进入具有相同基准的其他库,可以进一步阅读。 Comparison of Android networking libraries: OkHTTP, Retrofit, and Volley
答案 2 :(得分:4)
真正重要的是,你使用什么抽象,归结为Thread
。因此,每个Android的异步/并行类都在幕后使用Thread
/ Executor
,并且具有完全相同的潜在问题,例如线程所具有的锁定。
之间的区别在于它的'用法。例如,AsyncTask
定义了一个方便的完成回调 - onPostExecute()
。 CountDownTimer
允许您控制时间等。
当然,您可以使用普通Thread
,但在这种情况下,您需要投入更多时间自行解决可能出现的问题。
因此,Android为您提供了几种适合正确工作的合适工具。
答案 3 :(得分:3)
但许多人说“Asynctask已经过时”,不建议使用它们。
我没有遇到过这样说的人。但是,Android团队的工作是决定框架的某些部分何时过时或弃用。 CursorLoaders
使用使用AsyncTaskLoader
的{{1}}。 AsyncTask
是一种抽象,可以防止开发人员必须实现令人讨厌的AsyncTasks
状态逻辑。这意味着所有这些类在后台使用Thread
。
所以,Asynctask真的很糟糕,我应该使用框架 网络任务?我应该用什么背景(不是 网络)任务?
了解何时以及如何使用您的工具。你提到Threads
。在这种特殊情况下,当您阅读文档并稍微使用它时,您会意识到它有意与CursorLoader
平滑地集成。现在,ContentProviders
抽象出基础数据;您可以查询本地SQLite数据库或远程服务器。
通常,ContentProviders
用于检索“不太大”信息的简洁部分(用于与服务器通信时)。人们可能会说AsyncTasks
已过时,因为有更好(更有效)的方式与服务器进行交互(请参阅Retrofit
)。
答案 4 :(得分:2)
我认为AsyncTask
优于Thread
,因为它在主线程上提供回调。 Loader
优于AsyncTask
,因为它还会为您处理配置更改。
答案 5 :(得分:2)
AsyncTask可以正确,轻松地使用UI线程。此类允许您执行后台操作并在UI线程上发布结果,而无需操作线程和/或处理程序。
AsyncTask
旨在成为Thread和Handler的辅助类,并不构成通用的线程框架。理想情况下,AsyncTasks
应该用于短期操作(最多 几秒 。)
如果您需要长时间保持线程运行,强烈建议您使用java.util.concurrent
包提供的各种API,例如Executor
,ThreadPoolExecutor
和{{ 1}}。
从主线程中移动大量或长期任务,以便它们不会干扰平滑渲染和对用户输入的快速响应,这是您在应用中采用线程的最大原因。
使用它将长时间运行的计算与主线程(UI线程)分开
服务是一种可以在后台执行长时间运行的应用程序组件,它不提供用户界面。
服务可以从后台处理 网络交易,播放音乐,执行文件I / O或与内容提供商进行交互 。
IntentService是服务的基类,可根据需要处理异步请求(表示为Intents)。
所有请求都在一个工作线程上处理 - 它们可能需要多长时间(并且不会阻止应用程序的主循环), 但是只会处理一个请求一段时间。
Loader API允许您从内容提供商或其他数据源加载数据,以便在活动或片段中显示。
装载机解决了这些问题并包含其他好处。例如:
加载程序在不同的线程上运行,以防止janky或无响应的UI。
加载程序通过在事件发生时提供回调方法来简化线程管理。
那么,Asynctask是非常糟糕的,我应该使用框架进行网络任务?我应该将什么用于后台(而不是网络)任务?
使用FutureTask
处理持续时间小于5毫秒的工作项。您可以使用AsyncTask
或Thread
或Service
作为后台任务。