前提: Handler不是线程。
Looper
是与其创建的Thread
相关联的对象。从它的名称可以猜到,Looper
将循环执行某些操作,但是循环执行什么?它会循环执行与同一线程相关联的消息队列。
接下来的问题是:我如何将某些内容放入这个消息队列中?
这就是Handler
的作用。一个Handler
总是与一个Looper
相关联(哪一个?我们稍后会看到)。Handler
可以扮演两个角色(这可能就是为什么它很容易混淆的原因)。
Handler的第一个作用:你必须使用它将消息发布到与其关联的Looper(实际上是其消息队列)。您可以使用各种Handler.sendMessage*
(或Handler.post*
)方法来完成这一点。(请注意,sendMessageDelayed/postDelayed方法允许您在未来发布Message/Runnable以进行处理)。
与Handler相关联的Looper是什么?非常简单:如果不指定,则为当前线程的Looper;但是您可以使用具有Looper的构造函数:{{link3:new Handler(Looper looper)
}},在这种情况下,处理程序与参数中的looper相关联。
此时,我们知道:
- 一个 Looper 与一个 Thread 相关联
- 一个 Looper 循环遍历它的相关消息队列
- 因此:只要我们为 Thread 拥有了一个 Looper,就会有一个消息队列与之相关联
- 一个 Handler 总是与一个 Looper 相关联
- 一个 Handler 可以用于将消息发布到消息队列中
现在,让我们看看第二部分:消息处理/消息处理。
首先,让我们看一下
Looper
循环遍历其
消息队列。
队列中有消息吗?是的(即某个
Handler
已发布它)。
是否到了处理此消息的时间(如果使用
postDelayed发布)?如果不是,请稍等。如果是时候了:让我们分派这个消息。
记住我说过Handler有两个角色...这里是Handler的
第二个角色:Handler(如其名称所示)可以处理消息。为了能够处理自定义消息,您必须子类化
Handler
类并实现
handleMessage(Message)
方法。
因此,
Looper
将简单地调用发布消息的 Handler 的
handleMessage
,它的工作(即分发消息)完成后(Looper 可以继续处理队列中的下一条消息)。
此时,您可能会问自己:“好吧,我看到延迟消息的好处了,但为什么我要为立即执行的任务使用所有这些东西呢?”
请记住,
Looper
与一个线程相关联,并且将在该线程中调用
handleMessage
。另一方面,
Handler.post*
可以从另一个线程调用。因此,如果要从线程 Y 中的线程 X 安排作业,则此机制也非常方便。(如果作业影响 UI 并且必须在 UI 线程中运行,则特别有用)
最后注意:
在 Android 上,有一个与主线程(即 UI 线程)相关联的主 Looper。您可以使用
Looper.getMainLooper()
获取对它的引用,因此您可以创建与主 Looper 相关联的 Handler:
Handler myHandler = new Handler(Looper.getMainLooper());
使用此方法,您可以从任何线程向UI线程发布消息
- 你真的需要使用消息和子类化Handler来使用它吗?不一定(并非总是需要)
您不必始终显式创建消息以使用此机制。您可以轻松地将{{link1:Runnable
}}发布到Handler
中,在这种情况下,您甚至不需要覆盖handleMessage(Message)
,因为处理程序的默认实现将简单地执行Runnable
(在幕后:创建一个message,其中包含与其关联的Runnable)
默认情况下,每个线程上都没有Looper(默认情况下,仅在UI-Thread上准备了一个)。要为当前线程准备Looper:调用{{link3:Looper.prepare()
}}。