目录

6. Android 校招复习篇一・Handler

Handler

工作原理

概念

要了解原理首先我们要知道几个概念:

  • Handler:处理器
    • 定义1主线程子线程的通信媒介
    • 定义2:线程消息的主要处理者
    • 作用:负责将消息Message发送到消息队列MessageQueue以及处理循环器Looper分派过来的消息
  • MessageQueue:消息队列
    • 定义:一种先进先出的数据结构
    • 作用:用于存储Handler发过来的消息Message
  • Looper:循环器
    • 定义:消息队列MessageQueue与处理器Handler的通信媒介
    • 作用:用于消息循环
      • 消息获取:循环取出消息队列MessageQueue里的消息Message
      • 消息分发:将取出的消息Message发送给对应的处理器Handler
    • 备注
      • 每个线程只能拥有1个Looper
      • 1个Looper可绑定多个线程的Handler(即多个线程可往1个Looper所拥有的MessageQueue中发送消息,提供了线程间通信的可能)

工作流程

https://cdn.jsdelivr.net/gh/RebornQ/cdn.blog/img/reviews/Handler%E5%B7%A5%E4%BD%9C%E6%B5%81%E7%A8%8B.svg
Handler工作流程
  • 注意:
    • 主线程的Looper对象自动调用ActivityThread的静态方法main()中的Looper.prepareMainLooper()生成,同时会生成对应的MessageQueue对象;而子线程的Looper对象则需要手动通过Looper.prepare()创建

      • 在子线程若不手动创建Looper对象,则无法生成Handler对象。

        在创建Handler对象时,则通过构造方法自动关联当前线程的Looper对象 & 对应的消息队列对象MessagerQueue,从而自动绑定了实现创建Handler对象操作的线程。

    • Looper消息分发dispatchMessage(msg)时,会进行1次发送方式的判断(具体看源码):

      1. msg.callback属性不为空,则代表使用了post(Runnable r)发送消息,则回调Runnable对象里复写的run()
      2. msg.callback属性为空,则代表使用了sendMessage(Message msg)发送消息,则回调复写的handleMessage(msg)

常见面试问题

为什么Looper不断循环去处理消息却不会导致主线程卡死(ANR)?(2020蘑菇街面试真题)

系统每 16ms 会发送一个刷新 UI 消息唤醒。

Looper.loop()的死循环里面有两行代码:

1
2
Message msg = queue.next;
msg.target.dispatchMessage(msg);

这两行代码的作用就是从 消息队列MessageQueue 中不断地取出消息,然后把消息分发出去,给 Handler 处理,所以不会造成ANR。

因为 Android 是由事件驱动的,Looper.loop()不断地接收事件、处理事件,每一个点击触摸甚至是 Activity 的生命周期都是运行在Looper.loop()的控制下,如果他停止了,应用也随之停止了。

只能是某一个消息或者说对消息的处理阻塞了Looper.loop(),而不是Looper.loop()阻塞了它。

消息队列MessasgeQueue是一个什么样的结构?(2020蘑菇街面试真题)

存储特性为先进先出的数据结构,也就是队列

Handler/线程、Looper和MessageQueue的关系?(2020网易校招笔试原题)

Looper:负责从消息队列中拿消息,然后分发给线程中的 Handler 处理 MessageQueue:负责存储 Handler 发过来的消息 Handler:负责发消息到 MessageQueue 以及处理 Looper 分发过来的消息

Handler的post消息如何被执行?(2020网易校招笔试原题)

https://cdn.jsdelivr.net/gh/RebornQ/cdn.blog/img/reviews/Handler%E5%B7%A5%E4%BD%9C%E6%B5%81%E7%A8%8B-Handler.post.png
Handler工作流程-Handler.post