承接上一篇handler系列一,上篇主要总结了handler如何通信,这篇来介绍handler怎么通信。
handler的通信机制
handler,looper,messagequeue如何关联

创建handler,并采用当前线程的looper创建消息循环系统;
handler通过sendmessage(message)或post(runnable)发送消息,调用enqueuemessage把消息插入到消息链表中;
looper循环检测消息队列中的消息,若有消息则取出该消息,并调用该消息持有的handler的dispatchmessage方法,回调到创建handler线程中重写的handlemessage里执行。
handler及其关联的类图
以上类图可以快速帮助我们理清handler与looper、messagequeue的关系,以下从源码的角度慢慢分析:
上一段很熟悉的代码:
从sendmessagequeue开始追踪,函数调用关系:sendmessage -> sendmessagedelayed ->sendmessageattime,在sendmessageattime中,携带者传来的message与handler的mqueue一起通过enqueuemessage进入队列了。
对于postrunnable而言,通过post投递该runnable,调用getpostmessage,通过该runnable构造一个message,再通过 sendmessagedelayed投递,接下来和sendmessage的流程一样了。
在enqueuemessage中,通过messagequeue入队列,并为该message的target赋值为当前的handler对象,记住<code>msg.target</code>很重要,之后looper取出该消息时,还需要由<code>msg.target.dispatchmessage</code>回调到该handler中处理消息。
在messagequeue中,由message的消息链表进行入队列
构造looper时,构建消息循环队列,并获取当前线程
但该函数是私有的,外界不能直接构造一个looper,而是通过looper.prepare来构造的:
这里创建looper,并把looper对象保存在sthreadlocal中,那sthreadlocal是什么呢?
static final threadlocal sthreadlocal = new threadlocal();
theadlocal 如何保存与获取looper?
在<code>loop</code>中,一个循环,通过<code>next</code>取出messagequeue中的消息
若取出的消息为null,则结束循环,返回。
设置消息为空,可以通过messagequeue的quit和quitsafely方法通知消息队列退出。
若取出的消息不为空,则通过msg.target.dispatchmessage回调到handler中去。
looper把消息回调到handler的dispatchmessage中进行消息处理:
若该消息有callback,即通过post(runnable)的方式投递消息,因为在投递<code>runnable</code>时,把<code>runnable</code>对象赋值给了message的<code>callback</code>。
若handler的mcallback不为空,则交由通过<code>callback</code>创建handler方式去处理。
否则,由最常见创建handler对象的方式,在重写handlermessage中处理。
以一个时序图来总结handler的消息机制,包含上述如何关联looper和messagequeue的过程。
handler-looper-messagequeue时序图