Handler源码解析1
https://blog.csdn.net/qq_44076155/article/details/110676740
Handler源码解析2
https://blog.csdn.net/qq_44076155/article/details/110687066
Handler:发送和接收消息
Looper:用于轮询消息队列,一个线程只能有一个Looper
Message: 消息实体
MessageQueue: 消息队列用于存储消息和管理消息
handler机制就是一个传送带的运转机制。
1)MessageQueue就像履带。
2)Thread就像背后的动力,就是我们通信都是基于线程而来的。
3)传送带的滚动需要一个开关给电机通电,那么就相当于我们的loop函数,而这个loop里面的for循环就会带着不断
的滚动,去轮询messageQueue
4)Message就是 我们的货物了
App启动时,调用ActivityThread.main
创建主线程的looper并且开始loop处理事务
looper的创建
通过prepare方法,static final 修饰的唯一threadLocal变量保证了一个线程只能有一个looper
流程分析
子线程handler-》sendMessage -> messasgeQueue.enqueueMessage //消息队列队列的插入节点
looper.loop()-> messasgeQueue.next()-》handler.dispatchMessage()->handler.handleMessage()
1.handler的各种发送消息的方式都会进入下面方法,并且为msg设置target
2.然后调用MessageQueue的enqueueMessage
看源码发现消息队列是一个由单链表实现的优先级队列
以msg的when来进行排序,并且使用了插入排序算法
3.有了消息和消息队列,还需要有一个开关Looper.loop
源码中loop方法主体是一个死循环,唯一的退出方式是,当msg==null
中途通过queue.next不断的从MessageQueue中取出消息
4.那什么时候msg会等于null?再来看看MessageQueue.next方法
同样是一个死循环,而且有两种情况会进行阻塞 1.没有到msg的执行时间 2.消息队列为空
消息队列为空时,在next时已经阻塞起来了,所以不会返回null
下面有一行,if命中则会返回为null
继续查找源码,发现只有在MessageQueue.quit里面才会把mQuitting置为true
也就是说只有调用quit方法后才能结束loop
而且在主线程中不允许调用这个方法,因为loop结束了,整个app进程也就结束了
5.最后又回到loop里面,获取到msg后,调用dispatchMessage分发消息,由上面我们知道msg.target就是发送消息的那个handler
dispatch里面调用了handleMessage,到次完成整个流程
哪一个handler发送的msg,就会分发到哪一个handler上,由此,可以在线程1中用mhandler sendMessage
然后在线程2中写 handleMessage 实现线程间的通信
一个线程对应一个looper 一个lopper对应一个MessageQueue,1线程 1loopper 1messageQueue
而MessageQueue的next enqueueMessage 都是使用的对象锁
因此 1个线程只有一个可以操作MessageQueue 的地方