- Handler和Looper之间的关系,他们怎样通信的,怎么实现事件的分发
handler通过sendMessage()发送消息到MessageQueue中,然后looper的loop()方法不断从MessageQueue中去获取消息,然后回调msg.target.dispatchMessage方法,也就是最终消息由Looper交给Handler处理。
- 如何再一个非UI线程中启动一个Looper?
为了保证Handler关联的线程有Looper对象,可分一下两种情况:
- 在主UI线程中,系统已经初始化了一个Looper对象,因此程序直接创建Handler即可,然后就可以通过Handler来发送消息、处理消息了。(即之前写的博客:Handler详解(一)—关联到UI线程,非UI线程向UI线程中发送消息)参考:http://www.it610.com/article/5036824.htm
- 程序员自己启动的子线程,必须自己创建一个Looper对象,并启动它。创建Looper对象调用它的prepare()方法即可。prepare()方法保证每个线程最多只有一个Looper对象。UI线程向非UI线程发送消息。
- looper.loop()内部实现机制
loop()方法,不断从MessageQueue中去取消息,交给消息的target属性的dispatchMessage去处理。
- Looper、Handler、Message三者关系
1、首先Looper.prepare()在本线程中保存一个Looper实例,然后该实例中保存一个MessageQueue对象;因为Looper.prepare()在一个线程中只能调用一次,所以MessageQueue在一个线程中只会存在一个。
2、Looper.loop()会让当前线程进入一个无限循环,不端从MessageQueue的实例中读取消息,然后回调msg.target.dispatchMessage(msg)方法。
3、Handler的构造方法,会首先得到当前线程中保存的Looper实例,进而与Looper实例中的MessageQueue想关联。
4、Handler的sendMessage方法,会给msg的target赋值为handler自身,然后加入MessageQueue中。
5、在构造Handler实例时,我们会重写handleMessage方法,也就是msg.target.dispatchMessage(msg)最终调用的方法。
- 若消息队列为空,线程则会阻塞等待
- 对于Handler,如何获取当前线程的Looper?
如果在创建Handler时不指定与其绑定的Looper对象,系统默认会将当前线程的Looper绑定到该Handler上。
在主线程中,可以直接使用new Handler()创建Handler对象,其将自动与主线程的Looper对象绑定;在非主线程中直接这样创建Handler则会报错,因为Android系统默认情况下非主线程中没有开启Looper,而Handler对象必须绑定Looper对象。这种情况下,需先在该线程中手动开启Looper(Looper.prepare()-->Looper.loop()),然后将其绑定到Handler对象上;或者通过Looper.getMainLooper(),获得主线程的Looper,将其绑定到此Handler对象上。参考 利用Handler在主线程与子线程之间互发消息 https://blog.csdn.net/u011506413/article/details/50959969
- Handler机制中线程切换和消息阻塞再剖析
参考 :https://blog.csdn.net/yus201120/article/details/82015980