前提:处理程序不是线程。
A是与创建它Looper
的对象相关联的对象。Thread
正如你可以猜到它的名字 aLooper
会循环一些东西,但是循环什么呢?通过一个消息队列也与同一个线程相关联。
下一个问题是:我怎样才能在这个消息队列中放一些东西?
这是Handler
. AHandler
总是与 a 相关联Looper
(哪个?我们稍后会看到)。Handler
可以扮演两个角色(这可能是它令人困惑的原因)
Handler 的第一个角色:您必须使用它来将消息发布到它的关联 Looper(实际上是它的消息队列)。您可以使用各种Handler.sendMessage*
(或Handler.post*
)方法之一来做到这一点。(并注意 sendMessageDelayed/ postDelayed方法允许您发布消息/可运行以供将来处理)
与 Handler 关联的 Looper 是什么?非常简单:不指定当前线程的 Looper;但是您可以将构造函数与 Looper 一起使用:new Handler(Looper looper)
在这种情况下,处理程序与参数中的 looper 相关联。
在这一点上,我们知道:
- 一个 Looper 与一个且只有一个 Thread 相关联
- Looper 循环其关联的消息队列
- 结果:有一个消息队列与一个线程相关联(只要我们有线程的 Looper)
- 一个 Handler 总是与一个 Looper 相关联
- 可以使用 Handler 将消息发布到消息队列
现在,让我们看看第二部分:消息处理/消息处理。
首先,让我们看看它的消息队列Looper
上的循环。
队列中有消息吗?是的(即在某个时候,aHandler
已经发布了它。)是时候处理这条消息(如果它是用postDelayed发布的)吗?如果没有,请稍等。如果是时候:让我们发送此消息。
请记住,我告诉过 Handler 有两个角色……这里是Handler 的第二个角色:一个 Handler(如其名称所示)可以处理消息。为了能够处理自定义消息,您必须子类化Handler
该类并实现该handleMessage(Message)
方法。
因此,Looper
将简单地调用handleMessage
发布消息的处理程序,它的工作(即发送消息)完成(循环器可以移动到队列中的下一条消息)。
此时你可能会问自己:“好吧,我看到了延迟消息的兴趣,但为什么我要使用所有这些东西来立即做事情呢?”
记住 theLooper
与 one 相关联,Thread
并且handleMessage
将在 this 中调用Thread
。另一方面,Handler.post*
可以从另一个线程调用。所以这种机制也很方便从线程 Y 调度线程 X 中的作业。(如果作业正在影响 UI 并且必须在 UI-Thread 中运行,则特别有用)
最后说明
在 Android 上,有一个主 Looper 与主线程(即 UI 线程)相关联。您可以使用 获取对它的引用Looper.getMainLooper()
,因此您可以使用以下方法创建与主 Looper 关联的 Handler:
Handler myHandler = new Handler(Looper.getMainLooper());
并且您可以将消息从任何线程发布到 UI 线程
- 你真的应该使用消息和子类处理程序来使用它吗?否(并非总是)
您并不总是需要显式创建消息来使用此机制。您可以轻松地将 a 发布Runnable
到 a Handler
,在这种情况下,您甚至不需要覆盖 ,因为Handler的默认handleMessage(Message)
实现将简单地执行Runnable
默认情况下,每个线程上都没有 Looper(默认情况下,UI-Thread 中只有一个准备好的)。为当前线程准备 Looper:调用Looper.prepare()