Handler系列六:主线程Looper死循环不阻塞

141 阅读2分钟

在Android开发中,Handler 通常与 LooperMessageQueue 一起工作, 以在适当的线程(通常是UI线程,即主线程)上执行消息和Runnable对象。 虽然 Looper 的循环看起来是一个死循环,但它实际上是精心设计的, 以确保它不会阻塞UI线程执行其他必要的任务,如处理用户输入或绘制界面。

关键点

  1. Looper 和 MessageQueue

    • 每个线程可以有一个 Looper,它负责管理该线程的 MessageQueue(消息队列)。
    • 在Android的主线程(UI线程)中,系统已经为你创建了一个 Looper 和一个 MessageQueue。 这是通过调用 Looper.prepareMainLooper() 实现的,通常在 ActivityThread 的初始化过程中。
  2. Looper 的循环

    • Looper 的循环通过调用 Looper.loop() 启动,这个方法会一直运行, 不断地从 MessageQueue 中取出消息并处理它们。
    • ####这个Looper循环是事件驱动的,意味着它只有在队列中有消息时才会处理消息。 如果队列为空,Looper 会等待(阻塞)直到有新的消息到来。
  3. 消息处理机制

    • Handler 发送一个消息(Message)或 RunnableMessageQueue 时, 它实际上是在请求 Looper 在将来的某个时间点执行这个消息或 Runnable
    • 如果主线程正在执行其他任务(如处理用户输入或绘制界面),Looper 的循环将不会执行, 直到主线程空闲并且 MessageQueue 中有消息为止。
  4. 非阻塞特性

    • 由于 Looper 的循环是事件驱动的,并且它只在需要时从 MessageQueue 中取出消息, 因此它不会阻塞主线程执行其他任务。
    • 主线程可以在处理消息之间继续执行其他任务,如处理触摸事件、绘制界面等。

结论

尽管 Looper 的循环看起来像是一个死循环,

  • 但由于它是事件驱动的,并且只在有消息需要处理时才执行,因此它不会阻塞主线程执行其他重要任务。 这是Android系统能够保持流畅响应用户输入和界面更新的关键原因之一。

开发者在使用 Handler 时,不需要担心它会阻塞主线程,但应该注意不要在 Handler 的回调方法(如 handleMessage(Message msg))中执行耗时操作,因为这仍然会延迟主线程处理其他任务。对于耗时操作,应该使用后台线程(如 AsyncTaskIntentServiceThreadExecutorService)来处理。