3

处理程序是否是线程?如果是,我们如何从这个 Handler(thread) 更新 UI?

如果我们使用 Looper 的概念,那是可能的。在这种情况下,它是否适用于任何线程?我对这些线程、处理程序和 Loopers 感到非常困惑。任何人都可以用一个例子来解释他们吗?处理程序是否是线程?如果是,我们如何从这个 Handler(thread) 更新 UI。

如果我们使用 Looper 的概念,有可能,在这种情况下它适用于任何线程吗?我对这个 Thread、Handler 和 Looper 感到非常困惑。任何人都可以用一个例子来解释他们吗?


“ Thread 和 Handler 有什么区别”这个问题只是关于 Handlers 和 Threads 的问题,并没有解释 Loopers 和它们的行为。并且接受的答案说“另一方面,处理程序是允许您与 UI 线程通信(更新 UI)的后台线程”,但根据下面“ben75”的回答,处理程序不是线程。因此,我不认为这是该问题的重复。

4

2 回答 2

7

前提:处理程序不是线程。

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 中运行,则特别有用)

最后说明

  • UI线程是一等公民:

在 Android 上,有一个主 Looper 与主线程(即 UI 线程)相关联。您可以使用 获取对它的引用Looper.getMainLooper(),因此您可以使用以下方法创建与主 Looper 关联的 Handler:

Handler myHandler = new Handler(Looper.getMainLooper());

并且您可以将消息从任何线程发布到 UI 线程

  • 你真的应该使用消息和子类处理程序来使用它吗?否(并非总是)

您并不总是需要显式创建消息来使用此机制。您可以轻松地将 a 发布Runnable到 a Handler,在这种情况下,您甚至不需要覆盖 ,因为Handler的默认handleMessage(Message)实现将简单地执行Runnable

  • Looper 必须准备好(接收消息)

默认情况下,每个线程上都没有 Looper(默认情况下,UI-Thread 中只有一个准备好的)。为当前线程准备 Looper:调用Looper.prepare()

于 2014-10-13T16:05:09.417 回答
0

处理程序:

Handler 允许您发送和处理与线程的 MessageQueue 关联的 Message 和 Runnable 对象。每个 Handler 实例都与单个线程和该线程的消息队列相关联。当您创建一个新的处理程序时,它会绑定到创建它的线程的线程/消息队列——从那时起,它会将消息和可运行对象传递到该消息队列并在它们从消息中出来时执行它们队列。

现在,如果您想从不是主线程的其他线程更新 UI,您将首先Handler在主线程中创建一个并将其传递给任何后台线程。在后台线程中,您确实会使用该post (Runnable r)方法将消息发送回主线程,因为(阅读上面的段落):) Handlers 不是线程。

线:

线程是程序中的执行线程。

只是一个通用的后台处理任务。

活套:

Looper 是一个用于在队列中执行 Messages(Runnables) 的类。普通线程没有这样的队列,例如简单线程没有任何队列。它执行一次,在方法执行完成后,线程不会运行另一个 Message(Runnable)。

资料来源:
Looper 的目的是什么以及如何使用它?
线程和处理程序有什么区别

于 2014-10-13T14:10:54.120 回答