Handler, Message 消息传递机制
个人理解
在创建handler之前,必须确认已经在handler所在线程中调用了Looper.prepare(),因为在handler构造函数中会判断当前线程中是否有Looper对象,没有则报异常(无法在没有调用Looper.prepare()的线程中创建handler对象)
Looper.prepare作用:
1:判断当前线程中是否存在Looper对象,否则new一个ThreadLocal类型Looper对象,使得每个线程有独立的Looper,防止多线程传递消息时发生异常,是则报异常(一个线程中最多只能有一个Looper对象)。在Looper构造函数中创建了消息队列对象mQueue。
2:即1中创建了消息队列对象mQueue,将Looper和MessageQueue的对象“绑定”在一起。
在handler构造函数中,将handler所在线程中的Looper所创建的消息队列对象mQueue赋值给handler中声明的消息队列对象mQueue,将Looper,Handler,MessageQueue的对象“绑定”在一起。
发送消息:
Handler发送消息msg的方法经过封装调用最后跳转到sendMessageAtTime(Message msg, long uptimeMillis)方法(除了sendMessageAtFrontOfQueue(),这个方法将新的message放置到消息队列的头部),在其内部调用enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis)方法,将handler中声明的消息队列mQueue传入,通过msg.target = this, 将调用发送消息方法的handler对象(即this)与所发送的消息“绑定”,继续调用enqueueMessage的2个参数的方法,将传入的消息以队列排列。
接下来要取出消息队列中的消息,通过Looper.loop()方法实现,获得当前线程中的Looper对象,取出它的消息队列,通过for(;;)死循环取出队列中的消息,并调用msg.target.dispatchMessage(msg)方法(msg.target即是与发送消息“绑定”的handler),将取出的消息传回handler所在线程的handlemessage(msg)方法中,在里面更新UI,完成非UI线程和UI线程间的通信,解决因线程不安全不适合在非UI线程更新UI的问题。