Handler

作者: Amy木婉清 | 来源:发表于2020-12-24 14:02 被阅读0次

1. Handler 的基本原理

解释如下图:


图片

2. 子线程中怎么使用 Handler

  1. Looper.prepare 创建 Looper 并添加到 ThreadLocal 中
  2. Looper.loop 启动 Looper 的循环

3. MessageQueue 获取消息是怎么等待

通过 epoll 机制进行等待和唤醒。

4. 为什么不用 wait 而用 epoll 呢?

在 Android 2.2 及之前,使用 Java wait / notify 进行等待,在 2.3 以后,使用 epoll 机制,为了可以同时处理 native 侧的消息。

5. 线程和 Handler Looper MessageQueue 的关系

一个线程对应一个 Looper 对应一个 MessageQueue 对应多个 Handler。

6. 多个线程给 MessageQueue 发消息,如何保证线程安全

通过对 MessageQueue 加锁来保证线程安全。

7. Handler 消息延迟是怎么处理的

  1. 将传入的延迟时间转化成距离开机时间的毫秒数
  2. MessageQueue 中根据上一步转化的时间进行顺序排序
  3. 在 MessageQueue.next 获取消息时,对比当前时间(now)和第一步转化的时间(when),如果 now < when,则通过 epoll_wait 的 timeout 进行等待
  4. 如果该消息需要等待,会进行 idel handlers 的执行,执行完以后会再去检查此消息是否可以执行

8. View.post 和 Handler.post 的区别

View.post 最终也是通过 Handler.post 来执行消息的,执行过程如下:

  1. 如果在 performTraversals 前调用 View.post,则会将消息进行保存,之后在 dispatchAttachedToWindow 的时候通过 ViewRootImpl 中的 Handler 进行调用。
  2. 如果在 performTraversals 以后调用 View.post,则直接通过 ViewRootImpl 中的 Handler 进行调用。

9. Handler 导致的内存泄漏

①先说handler导致activity内存泄露的原因:

handler发送的消息在当前handler的消息队列中,如果此时activity finish掉了,那么消息队列的消息依旧会由handler进行处理,若此时handler声明为内部类(非静态内部类),我们知道内部类天然持有外部类的实例引用,那么就会导致activity无法回收,进而导致activity泄露。

②为何handler要定义为static?

因为静态内部类不持有外部类的引用,所以使用静态的handler不会导致activity的泄露

③为何handler要定义为static的同时,还要用WeakReference 包裹外部类的对象?

这是因为我们需要使用外部类的成员,可以通过"activity. "获取变量方法等,如果直接使用强引用,显然会导致activity泄露。

10. 非 UI 线程真的不能操作 View 吗

不能操作,原因是 ViewRootImpl 会检查创建 ViewRootImpl 的线程和当前操作的线程是否一致。而 ViewRootImpl 是在主线程创建的,所以非主线程不能操作 View。

相关文章

网友评论

      本文标题:Handler

      本文链接:https://www.haomeiwen.com/subject/bofmnktx.html