Handler vs AsyncTask vs Thread
Handler vs AsyncTask vs Thread
已关闭。这个问题是基于观点的。它目前不接受答案。
想改进这个问题吗?通过编辑这篇文章,更新问题以便它可以通过事实和引用来回答。
改进问题
我对Android中的Handlers
、AsyncTask
和Threads
之间的区别有点困惑。我已经阅读了很多博客和StackOverflow上的问题。
Handler
是后台线程,可以让您与UI通信。例如,更新进度条应该通过Handler
完成。使用Handlers有 MessagingQueues
的优势,因此如果您希望安排消息或更新多个UI元素或有重复的任务,这很有用。
AsyncTask
是类似的,实际上,它们利用了Handler
,但不在UI线程中运行,因此适用于获取数据,例如获取Web服务。
Thread
不能与UI交互,提供更基本的线程控制,而且你将会失去所有 AsyncTask
的抽象。
然而,我想在服务中运行一个套接字连接,这应该运行在处理程序(handler)中还是线程中,甚至在 AsyncTask
中?完全没有必要与UI进行交互。是否使用哪种方法会影响性能?
与此同时,文档已经得到了大量改进。
正如Vogella网站上关于Android后台处理的教程所介绍的那样:Android后台处理的Handlers、AsyncTask和Loaders:
Handler
类可用于在线程中注册,为其提供一个向该线程发送数据的简单通道。
AsyncTask
类封装了后台进程的创建和与主线程的同步。它还支持报告运行任务的进度。
而Thread
实际上是多线程的核心元素,开发人员可以使用它,但以下特点都需要自己来实现:
如果您使用Java线程,则必须处理以下要求:
- 如果要将结果返回到用户界面,则必须与主线程进行同步
- 没有默认方法来取消线程
- 没有默认线程池
- 没有默认处理Android中的配置更改
关于AsyncTask
,正如Android开发者参考所述:
AsyncTask
实现了UI线程的正确简单地使用。此类允许在后台执行操作,并在UI线程上发布结果,而无需操作线程和/或处理程序。
AsyncTask
旨在成为围绕Thread
和Handler
的辅助类,而不是通用的线程框架。 AsyncTasks应该理想地用于短时间操作(最多几秒钟)。如果需要长时间运行线程,则强烈建议使用java.util.concurrent包提供的各种API,例如Executor、ThreadPoolExecutor和FutureTask。
2015年5月更新:我发现了一系列关于这个主题的优秀讲座。
这是Google搜索:Douglas Schmidt lecture android concurrency and synchronisation
所有这些都是范德堡大学的CS 282(2013):面向Android的系统编程的一部分。这里是YouTube播放列表
Douglas Schmidt似乎是一位优秀的讲师
重要提示:如果你正考虑使用AsyncTask
来解决线程问题,你应该先查看ReactiveX/RxAndroid
,可能会有更合适的编程模式。一个非常好的资源是通过示例学习Android上的RxJava 2。
如果我们查看源代码,将会看到 AsyncTask
和 Handler
是纯粹使用Java编写的。(有些例外,但那不是重点)
所以,AsyncTask
和 Handler
没有什么奇迹,这些类使得开发人员的生活更加轻松。
例如:如果程序A调用方法A(),方法A() 可以在一个与程序A不同的线程中运行。通过以下代码可以很容易地验证:
Thread t = Thread.currentThread(); int id = t.getId();
为什么我们应该使用新的线程来执行一些任务呢?你可以通过谷歌搜索来了解,很多的原因,例如:重负荷、长时间运行的任务等。
那么,Thread
、AsyncTask
和 Handler
之间有什么区别呢?
AsyncTask
和 Handler
是用Java编写的(内部使用了一个 Thread
),所以使用 Handler
或 AsyncTask
可以完成一切操作。
Handler
和 AsyncTask
真正帮助我们做什么呢?
最明显的原因是在调用线程和工作线程之间进行通信。(调用线程:调用 工作线程 执行某些任务的线程。调用线程不一定是 UI 线程)。当然,我们可以以其他方式在两个线程之间进行通信,但由于线程安全问题,这种方式存在许多缺点(和危险)。
这就是为什么我们应该使用 Handler
和 AsyncTask
的原因。这些类为我们完成了大部分工作,我们只需要知道要重写哪些方法。
Handler和AsyncTask之间的区别在于:当调用线程是UI线程时,请使用
AsyncTask
。这就是安卓文档所说的:
AsyncTask使得使用UI线程更加适当和简单。该类允许在UI线程上执行后台操作并发布结果,而无需操作线程和/或处理程序。
我想强调两点:
1)易于使用UI线程(因此,当调用线程是UI线程时使用)。
2)无需操作处理程序。(即:你可以使用Handler代替AsyncTask,但AsyncTask是一个更容易的选择)。
这篇文章中还有许多我尚未提及的内容,例如:什么是UI线程,或为什么使用AsyncTask更加容易。你必须了解每个类背后的一些方法并使用它,你才能完全理解原因。
注意:当你阅读安卓文档时,你会看到:
Handler允许您发送和处理与线程的消息队列相关联的消息和可运行对象。
这个描述一开始可能会很奇怪。我们只需要了解每个线程都有一个消息队列(就像待办事项列表),线程会接受每个消息并执行它,直到消息队列为空(就像我们完成工作并睡觉)。因此,当Handler通信时,它只是给调用线程发送一条消息并等待进行处理。
复杂吗?只需记住Handler可以安全地与调用线程通信即可。