理解Handler机制前需要了解一下什么是Handler?作用是什么?Handler就是用来处理子线更新UI问题的;接收子线程发送来的数据, 然后更新到主线程。
了解Handler消息机制,就需要了解它的几个重要参与者。
Handler : 消息机制中的发起者。使用Handler,会先在声明时初始化Handler实例。在Handler构造中,会拿到Looper的实例,通过looper的实例初始化消息队列。
mLooper = Looper.myLooper(); if (mLooper == null) { throw new RuntimeException( "Can't create handler inside thread that has not called Looper.prepare()"); } mQueue = mLooper.mQueue;
这样就保证了handler的实例与我们Looper实例中MessageQueue关联上了。当我们调用发消息的方法时: sendMessage();经过跳转回到sendMessageAtTime()方法。在这个方法内部,调用了MessageQueue的enqueueMessage方法。消息就由Handler转到保存到了消息队列中去了。之前在讲述Looper时,Looper会调用prepare()和loop()方法,在当前执行的线程中保存一个Looper实例,这个实例会保存一个MessageQueue对象,然后当前线程进入一个无限循环中去,不断从MessageQueue中读取Handler发来的消息,回调创建这个消息的handler中的dispathMessage方法。在dispathMessage方法,调用了handleMessage方法。然后我们创建handler的时候都是复写handleMessage方法,然后根据msg.what进行消息处理了。
Looper:消息机制中的发动机。无限循环消息队列。主要两个方法,prepare()和looper()方法。首先在Looper的构造中,创建了一个MessageQueue(消息队列)。并且将当前运行线程赋值给所创建的线程。
prepare()方法: Looper的实例放入了ThreadLocal对象中,并且判断了ThreadLocal对象是否为null,否则抛出异常。这也就说明了Looper.prepare()方法不能被调用两次,同时也保证了一个线程中只有一个Looper实例;
looper方法:从looper实例中的拿到一个mQueue(消息队列):
final Looper me = myLooper(); if (me == null) { throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread."); } final MessageQueue queue = me.mQueue;
然后进入无线循环中。(就是在一个死循环中,根据消息队列的消息是否为空来判断,只有堆列中存在消息时,才开始执行下一步,否则阻塞);当拿到消息后,把消息交给msg的target的dispatchMessage方法去处理:msg.target.dispatchMessage(msg);然后释放消息资源。loopr()方法结束。
Mssage:消息对象,携带需要传递的数据。
MessageQueue: 一个消息队列,保存发出的消息,并且是阻塞队列,只有堆列中存在消息时,才开始执行下一步,否则阻塞。
最后总结:
1、首先创建并初始化Handler实例,在Handler的构造方法,会首先得到当前线程中保存的Looper实例,从Looper中获取MessageQueue,进而与Looper实例中的MessageQueue想关联。
2、而获得Looper实例时,在Looper.prepare()方法中会在本线程中保存一个Looper实例,然后该实例中保存一个MessageQueue的对象;因为Looper.prepare()在一个线程中只能调用一次,所以MessageQueue在一个线程中只会存在一个。
3、然后,Looper.loop()会让当前线程进入一个无限循环,不端从MessageQueue的实例中读取消息,然后回调msg.target.dispatchMessage(msg)方法。
for (;;) { Message msg = queue.next(); // might block if (msg == null) { // No message indicates that the message queue is quitting. return; } .......... }
4、当调用Handler的sendMessage方法,最后会跳转到enqueueMessage方法中,会给msg的target赋值为handler自身,msg.target = this;,然后加入MessageQueue中。这个this就是当前Handler本身。
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) { msg.target = this; if (mAsynchronous) { msg.setAsynchronous(true); } return queue.enqueueMessage(msg, uptimeMillis); }
5、最后,在构造Handler实例时重写的handleMessage方法中,也就是msg.target.dispatchMessage(msg)最终调用的方法,就可以拿到发出的消息了。