示意图:
类结构示意图:
时序图:
从示意图可以看出来,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类就能使用背后极其复杂的消息机制。(最少知识原则(LKP))
Handler的post()和postDelayed()方法的异同?
- 底层都是调用的sendMessageDelayed()->sendMessageAtTime()
- post()传入的时间参数为0
- postDelayed()传入的时间参数是需要的时间间隔。