Handler消息机制学习记录

示意图:

类结构示意图:

时序图:

从示意图可以看出来,MessageQueue和子线程是一对多的关系,MessageQueue和Looper是 一对一的关系。

那么如何做到,不同的子线程向消息队列压入消息,拿到的是同一个消息队列呢?

      答:把 MessageQueue和Looper绑定好,子线程拿到Looper对象,就能拿到MessageQueue对 象。

什么时候去拿Looper对象?

      答:Looper跟主线程是一对一的绑定关系,想要在主线程中获取到Looper对象,那Handler的 实例化就要在主线程中进行,所以Looper对象应该在Handler实例化的时候去获取。

为什么要在主线程更新UI?

      答:系统设计者,为了考虑到用户体验,系统性能

子线程要更新UI,怎么办?

      答:通过消息机制给主线程发送消息,让主线程更新UI,这个消息机制就是Handler

Handler只能用来更新UI吗?

      答:Handler其实主要用来线程通信 也就是可能会出现子线程和子线程通信的情况,那么轮询器Looper初始化就有可能出现在 子线程中,如何保证Looper对象能够在子线程中被正确获取,用于loop轮询呢?答案是 ThreadLocal

ThreadLocal是什么?

      答:ThreadLocal并不是一个Thread,而是Thread的局部变量。 ThreadLocal为解决多线程的并发问题而生。 它使变量在每个线程中都有独立拷贝,不会出现一个线程读取变量时而被另一个线程修改的 现象。

为什么最终还是要回到handleMessage()这个方法处理次消息?

      答:因为最终是要回到handleMessage()这个方法,所以先在Message类里面定义了一个Handler引用target,然后在Handler类的sendMessage方法里赋值msg.target = this,接着就是在Looper轮询方法loop里面取到了Message对象msg,并且直接调(转发)msg.target.dispatchMessage(msg)方法就可以回到最终是要回到handleMessage()这个方法里面了。

为什么要msg.target = this(就是为什么Message要带一个target)?

      答:Handler中最少知识原则的应用 Handler既是消息的发送者,也是消息的处理者 只通过一个Handler类就能使用背后极其复杂的消息机制。

Handler的post()和postDelayed()方法的异同?

  1. 底层都是调用的sendMessageDelayed()->sendMessageAtTime()
  2. post()传入的时间参数为0
  3. postDelayed()传入的时间参数是需要的时间间隔。

猜你喜欢

转载自blog.csdn.net/m0_37670495/article/details/109305342