一 .Handler的执行过程
1.定义Handler对象,重写handleMessage方法
2.handler 对象调用sendMessage 发送message,sendMessage 最终调用 sendMessageAtTime
3.sendMessageAtTime方法又调用了 enqueueMessage 使message 加入到 消息队列 MessageQueue,并且执行了msg.target = this 把handler对象赋值给message对象的target属性
4.线程中的Looper执行loop()方法,不断从消息队列当中读取消息。
5.loop()取到消息后,执行 msg.target.dispatchMessage(msg) ,也就是执行Handler对象当中的dispatchMessage方法
6.最终dispatchMessage 方法,可以执行第一步handler对象重写的handleMessage继而完成了整个消息传递
补充 7.如果,第二步中Handler 使用post方法发送一个runable对象而非send方法,runable传递给了message的callback,最终在dispatchMessage 中,判断callback!=null从而执行了runable对象
二 .相关类
A.Handler:作用是发送消息,执行消息
Handler的相关方法已经介绍过了,这里 ,最终发送消息都指向了sendMessageAtTime(除了sendMessageAtFrontOfQueue)
//sendMessageAtTime源码
public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
MessageQueue queue = mQueue;
if (queue == null) {
RuntimeException e = new RuntimeException(
this + " sendMessageAtTime() called with no mQueue");
Log.w("Looper", e.getMessage(), e);
return false;
}
return enqueueMessage(queue, msg, uptimeMillis);
}
最终执行消息都指向了dispatchMessage
B. Message:消息,target属性携带handler对象,callback属性可携带Runable对象
C.MessageQueue:消息队列,一个线程只有一个消息队列
类似现实中买票,每个人都是一个messge,如果不排队窗口售票员处理不过来,票也容易卖重复了。排成一队,一个一个处理。
sendMessageAtTime中调用了MessageQueue 的 enqueueMessage 方法使消息加入消息队列。
Looper调用MessageQueue的next方法从消息队列中取消息。
D.Looper:循环从MessageQueue里面取消息,并dispatch调度消息。每个线程一个Looper实例
1. Looper才是使消息队列循环起来的类,在UI主线程中,
Actitivy创建的时候,已经执行了Looper.loop() 。在Activity源码中定义了变量ActivityThread 类型的变量 mMainThread,他就代表了主线程。ActivityThread 中定义了Looper,并最终执行了
Looper.loop()。所以在主线程中,可以直接发送消息,并且取消息。
2.但是在Thread中,并没有定义和调用Looper.loop(),这样你发消息取不出来,执行不了,所以,在子线程要想执行Handler 这一套机制,必须在Thread里调用Looper.loop()是消息循环起来
Handler机制的作用什么,
是让线程A发消息,告诉B线程执行消息。
这里既可以
子线程发送消息,让
主线程执行消息; 又可以主线程发消息让子线程执行消息。
Handler
发消息的线程
和
消息执行的线程
是两个概念。这里,子线程里给主线程send消息,会使消息在主线程执行。 主线程给子线程send消息,会使消息在子线程执行。
进一步,主线程在创建的时候,就已经执行了Looper.loop() 监听消息队列。 所以子线程发消息给主线程,可以随时就执行了
但是,主线程发消息给子线程,子线程默认又没有监听消息队列,发了消息没人收。所以才需要先执行
Looper.prepare() 使线程绑定Looper对象,然后执行Looper.loop() 使消息队列动起来,循环监听消息队列。
实际上,主线程发消息让子线程执行消息是不常见的,主要是为了解释清楚 Looper.prepare() 是和线程绑定,Looper.loop() 可以使线程循环监听消息队列。Looper才不管你是不是主线程,它只是让绑定它的线程具有循环监听消息队列的功能