何时使用Service、AsyncTask或Handler?

34

有人能告诉我真正的区别吗?


vs 线程:https://dev59.com/wmw05IYBdhLWcg3w41wp - Ciro Santilli OurBigBook.com
5个回答

24
我的经验准则是,当我想要执行与单个Activity相关的操作时,使用AsyncTask,而当我想要执行在启动它的Activity处于后台时仍然继续的操作时,使用Service。因此,如果我想在Activity中进行少量的后台处理而不阻塞UI,我会使用AsyncTask。然后,我将使用该Activity的默认Handler传递消息,以确保更新发生在主线程上。在主线程上处理更新有两个好处:UI更新正确,并且您不必太担心同步问题。
例如,如果我想要下载可能需要一段时间的内容,我会使用Service。这样,如果我转到应用程序的另一个Activity或完全另一个应用程序,我的Service可以继续运行并继续下载文件,因此当我返回到我的应用程序时,文件已准备好。在这种情况下,下载完成后我可能会使用状态栏通知,以便用户可以选择在方便的时间返回到我的应用程序。
如果您在AsyncTask中使用长时间运行的进程,您会发现即使在导航离开Activity后,它也可能会继续运行。
  • 如果当你的处理完成时Activity在后台运行,那么当你尝试用结果等更新UI时可能会出现问题。
  • 当Android需要内存时,后台的ActivityService更容易被杀掉。

2
这个答案真的很到位。关于使用AsyncTaskService时可能出现的问题的最后一点是决定使用哪种方式的关键因素。我认为第一个限制仍然可以解决-不要直接从AsyncTask更新UI,而是像在Service中一样做(广播一个意图,显示通知,或将数据插入到ContentProvider中以供稍后由Activity获取)。然而,第二点-关于Activity更容易被杀死-那是最相关的点。 - curioustechizen

14

当需要长时间在后台运行某些任务时,请使用Service。它不绑定到任何活动。典型的例子是音乐播放器。
AsyncTask 在当前活动中有一些必须在后台完成的任务时非常好用,例如下载、搜索文件中的文本等。
个人而言,我仅使用Handlers将更改发布到UI线程。例如,在后台线程中进行一些计算,并通过处理程序发布结果。

最重要的是:在大多数情况下,AsyncTask 就是您需要的。


4
你实际上更喜欢使用处理程序来更新UI线程,而不是AsyncTasks吗? - IgorGanapolsky

5
为了补充其他回答关于服务和AsyncTask区别的内容,值得注意的是[0]:
- 服务不是一个单独的进程。服务对象本身并不意味着它在自己的进程中运行;除非另有规定,否则它将在与应用程序相同的进程中运行。 - 服务不是线程。它本身不是在主线程之外执行工作的手段(以避免应用程序无响应错误)。
服务往往是描述应用程序重要部分的东西,而不是AsyncTask,后者通常有助于Activity和/或改善UI响应性。除了提高代码清晰度外,服务还可以与其他应用程序共享,为您的应用程序与外界之间提供清晰的接口。
与其说是一本书,我会说开发人员指南有很多好的答案。
[0] 来源:http://developer.android.com/reference/android/app/Service.html#WhatIsAService

4
  • AsyncTask: 当我希望在不阻塞UI的情况下执行某些操作,并在UI上反映出更改时,使用AsyncTask。

例如:在按钮单击时下载某些内容,仍停留在同一活动中并显示进度条/滑块以更新已下载的百分比。如果活动进入后台,则可能会发生冲突。

  • Service: 当我希望在后台执行不需要更新UI的操作时,请使用Service。它不关心应用程序是在前台还是后台运行。

例如:当从Android Market下载的任何应用程序在状态栏中显示通知并且UI返回到先前的页面并允许您执行其他操作时。


1
请注意,AsyncTask 不一定需要更新 UI。因此,您提到的 Service 的使用情况也可以使用 AsyncTask 实现:只需不要在 onProgressUpdate()onPostExecute() 方法中更新 UI。 - curioustechizen

1

服务

服务是一个应用程序组件,可以在后台执行长时间运行的操作并不提供用户界面。另一个应用程序组件可以启动服务,即使用户切换到另一个应用程序,它也将继续在后台运行。此外,组件可以绑定到服务以进行交互。

何时使用?

没有用户界面的任务,但不应该太长。对于长时间的任务,请在服务内使用线程。 一般情况下的长任务。

触发:调用onStartService()方法

触发自:任何线程

运行于:其托管进程的主线程。服务不会创建自己的线程,也不会在单独的进程中运行(除非您另有指定)

限制/缺点:可能会阻塞主线程


AsyncTask

AsyncTask允许正确且轻松地使用UI线程。该类允许在后台执行操作并在UI线程上发布结果,而无需操纵线程和/或处理程序。异步任务由在后台线程上运行的计算定义,并在UI线程上发布其结果。

何时使用?

需要与主线程通信的小型任务 对于并行任务,请使用多个实例或Executor 可能需要花费数毫秒以上时间的磁盘绑定任务

触发器:调用execute()方法

触发源:主线程

运行于:工作线程。但是,在发布进度期间可能会调用主线程方法。

限制/缺点:

  • 一个实例只能执行一次(因此不能在循环中运行)
  • 必须从主线程创建并执行

参考链接


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接