android - 处理程序是否是线程,具有处理程序和线程的Looper的作用是什么?

标签 android multithreading android-handler android-looper

处理程序是线程还是非线程?如果是,我们如何从该Handler(thread)更新UI?

如果我们使用Looper概念,则有可能实现。在这种情况下,它是否适用于任何线程?我对这些线程,处理程序和循环程序非常困惑。有人可以举例说明吗?
处理程序是线程还是非线程?如果是,我们如何从该Handler(thread)更新UI。

如果我们使用Looper概念,则可能是可行的,在这种情况下,它是否适用于任何线程?我对此线程,处理程序和Looper感到非常困惑。有人可以举例说明吗?

问题“What is the difference between a Thread and a Handler”仅与处理程序和线程有关,而没有解释Looper及其行为。并接受的答案是:“另一方面,处理程序是允许您与UI线程进行通信(更新UI)的后台线程”,但是根据下面“ben75”的答案,处理程序不是线程。因此,我认为这不是该问题的重复。

最佳答案

前提:处理程序不是线程。
Looper是与创建它的Thread关联的对象。正如您所猜测的那样,Looper将遍历某些内容,但是遍历哪些内容呢?在消息队列上也与同一线程相关联。

下一个问题是:如何在此消息队列中放入内容?

这是HandlerHandler始终与Looper相关联(哪一个?我们将在以后看到)。 Handler可以扮演2个角色(这也许就是它令人困惑的原因)

处理程序的第一个角色:必须使用它将消息发布到与它关联的Looper(实际上是它的消息队列)中。您可以使用各种Handler.sendMessage*(或Handler.post*)方法之一来执行此操作。 (并注意sendMessageDelayed/postDelayed方法,使您可以发布Message/Runnable以便将来处理)

与Handler相关联的Looper是什么?非常简单:如果不指定当前线程的Looper,则为:但您可以将构造函数与Looper: new Handler(Looper looper) 一起使用,在这种情况下,处理程序与参数中的looper关联。

至此,我们知道:

  • 一个Looper与一个且仅一个线程相关联
  • 一个Looper在其关联的消息队列
  • 上循环
    结果是
  • :与一个线程关联一个消息队列(一旦我们为该线程添加了Looper)
  • Handler始终与一个Looper关联
  • 可以使用Handler将消息发布到消息队列


  • 现在,让我们看第二部分:消息处理/消息处理。

    首先,让我们看一下它的消息队列上的Looper循环。

    队列中是否有消息?是(即在某个时候,Handler已将其发布。)
    是时候处理此消息了(如果它是与postDelayed一起发布的)?如果没有,请稍等。如果是时间:让我们发送此消息。

    记住,我告诉过Handler有2个角色...这是Handler 的第二个角色:一个Handler(如其名称所示)可以处理消息。为了能够处理自定义消息,您必须子类化Handler类并实现 handleMessage(Message) 方法。

    因此,Looper将仅调用发布消息的Handler的handleMessage,并且其工作(即分发消息)已完成(Looper可以继续前进到队列中的下一个Message)。

    此时,您可能会问自己:“好吧,我看到了延迟发送消息的好处,但是为什么我应该将所有这些东西用于立即处理?”

    请记住,Looper与一个Thread相关联,并且handleMessage将在此Thread中调用。另一方面,可以从另一个线程调用Handler.post*。因此,这种机制从线程Y计划线程X中的作业也非常方便。(如果该作业影响UI且必须在UI线程中运行,则特别有用)

    最后的笔记
  • UI线程是一等公民:

  • 在Android上,有一个与主线程(即UI线程)关联的主Looper。您可以使用Looper.getMainLooper()对其进行引用,因此您可以使用以下命令创建与主Looper关联的Handler:
    Handler myHandler = new Handler(Looper.getMainLooper());
    

    这样您就可以将消息从任何线程发布到UI线程
  • 您是否真的应该使用消息和Handler的子类来使用它?否(并非总是如此)

  • 您不必总是显式创建消息来使用此机制。您可以轻松地将 Runnable 发布到Handler,在这种情况下,您甚至不需要覆盖handleMessage(Message),因为Handler的默认实现将简单地执行Runnable(在幕后:创建了message并关联了Runnable )
  • Looper必须准备好(接收消息)

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

    关于android - 处理程序是否是线程,具有处理程序和线程的Looper的作用是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26341955/

    相关文章:

    java - 如何将 Activity 更改为 Fragment

    android - 我们如何区分 Android M 的运行时权限中的从不询问和停止询问?

    python - OpenCV 适用于线程,但不适用于进程

    android - ....com.android.tools.aapt2.Aapt2Exception :. AAPT2 错误:查看日志了解详情

    android - 进度对话框在异步任务中给出异常

    java - Thread.Interrupt() 在 Android 中没有按预期工作?

    ios - 异步数据调用 & CoreAnimation

    android - 从推送通知 IntentService 中发布时,Handler 中的 Runnable 不运行

    android - 我在使用单独的线程时得到 `android.os.NetworkOnMainThreadException`

    android - 处理程序不会在 Activity 重启时再次执行