【安卓笔记】Handler,Looper,MessageQueue,Message源码分析
class LooperThread extends Thread { public Handler mHandler; public void run() { Looper.prepare(); mHandler = new Handler() { public void handleMessage(Message msg) { // process incoming messages here } }; Looper.loop(); } }
public final class Message implements Parcelable { public int what; public int arg1; public int arg2; public Object obj; long when; Bundle data; Handler target; Runnable callback; // sometimes we store linked lists of these things Message next; private static final Object sPoolSync = new Object(); private static Message sPool; private static int sPoolSize = 0; private static final int MAX_POOL_SIZE = 50; ... ...四个公有变量相信大家都不陌生,这里就不再介绍了。我们看到Message还有一些成员变量,比如说target,这是个Handler对象,target可以通过set方法或者obtainMessage等方式设置,一旦设置了Target,这个message就被绑定到一个具体的handler上了,然后message内部即可调用sendToTarget方法将message交给绑定的Handler进行处理,内部也调用的是sendMessage:
public void sendToTarget() { target.sendMessage(this); }
public static Message obtain() { synchronized (sPoolSync) { if (sPool != null) { Message m = sPool; sPool = m.next; m.next = null; sPoolSize--; return m; } } return new Message(); }recycle方法又会将用完的Message回收:
public void recycle() { clearForRecycle(); synchronized (sPoolSync) { if (sPoolSize < MAX_POOL_SIZE) { next = sPool; sPool = this; sPoolSize++; } } }
public final boolean sendMessage(Message msg) { return sendMessageDelayed(msg, 0); }sendMessage方法调用了sendMessageDelayed方法,延时设为0,继续跟源码:
public final boolean sendMessageDelayed(Message msg, long delayMillis) { if (delayMillis < 0) { delayMillis = 0; } return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis); }先是判断延时参数的合法性,然后调用了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); }跟到这一步,我们发现了一个没见过的变量,mQueue,查看该变量定义:
...... final MessageQueue mQueue; final Looper mLooper; final Callback mCallback; ......原来mQueue是一个消息队列,那么消息队列是怎么初始化的呢?我们找到Handler的一个构造器:
public Handler(Callback callback, boolean async) { ... ... mLooper = Looper.myLooper(); if (mLooper == null) { throw new RuntimeException( "Can‘t create handler inside thread that has not called Looper.prepare()"); } mQueue = mLooper.mQueue; mCallback = callback; mAsynchronous = async; }原来mQueue是Looper的成员变量,这个构造器通过Looper.myLooper方法返回了一个与当前线程绑定的Looper对象,进而获取到与Looper绑定的MessageQueue。这是Looper的构造器:
private Looper(boolean quitAllowed) { mQueue = new MessageQueue(quitAllowed); mRun = true; mThread = Thread.currentThread(); }既然我们知道了mQueue的来历,那么我们继续随着上面的思路跟进吧!刚才我们通过跟踪sendMessage源码发现内部最终调用了sendMessageAtTime方法,而这个方法又调用了enqueueMessage方法,从名字上能看出,该方法是将消息出队的方法,等等。。消息出队不应该是消息队列的方法么?怎么Handler也有?别急,我们查看enqueueMessage方法源码:
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) { msg.target = this;//我觉得这里应该判断target是否已经存在,如果存在就没必要设置了吧? if (mAsynchronous) { msg.setAsynchronous(true); } return queue.enqueueMessage(msg, uptimeMillis); }
final boolean enqueueMessage(Message msg, long when) { if (msg.isInUse()) {//消息是否正在使用 throw new AndroidRuntimeException(msg + " This message is already in use."); } if (msg.target == null) {//是否绑定handler throw new AndroidRuntimeException("Message must have a target."); } boolean needWake; synchronized (this) { if (mQuiting) { RuntimeException e = new RuntimeException( msg.target + " sending message to a Handler on a dead thread"); Log.w("MessageQueue", e.getMessage(), e); return false; } msg.when = when; Message p = mMessages; if (p == null || when == 0 || when < p.when) { // New head, wake up the event queue if blocked. msg.next = p; mMessages = msg; needWake = mBlocked; } else { needWake = mBlocked && p.target == null && msg.isAsynchronous(); Message prev; for (;;) { prev = p; p = p.next; if (p == null || when < p.when) { break; } if (needWake && p.isAsynchronous()) { needWake = false; } } msg.next = p; // invariant: p == prev.next prev.next = msg; } } if (needWake) { nativeWake(mPtr); } return true; }跟到这里终于明白了,这个MessageQueue是通过mMessages变量来记录当前待处理的消息,通过Mesage的发送的时间进行排序(调用msg.next)。
到这里整个入队操作就分析完了,通过这一系列的操作,handler将消息发送给了消息队列。到这里消息只是不断被加到消息队列中,我们并没有取出消息。那么Handler的handMessage方法又是怎么被调用的呢??带着这个疑问,我们来研究下Looper,消息泵,既然是泵,之所以叫泵,是因为它可以从消息队列中取出消息!之前说过,要在线程中使用Handler,必须调用Looper的prepare方法创建Looper对象,然后调用loop方法让消息队列运作起来。那么,这个loop方法是关键,我们查看该方法源码:
public static void loop() { 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; Binder.clearCallingIdentity(); ... ... for (;;) { Message msg = queue.next(); // might block if (msg == null) { return; } ... ... msg.target.dispatchMessage(msg); ... ... msg.recycle(); } }这个方法首先获取到消息队列的一个引用,然后在一个死循环中反复调用消息队列的出队方法(next)获取到下一个待处理的消息的引用,然后调用该消息所绑定的handler的dispatchMessage方法分发消息,最后将该消息回收。我们跟踪Handler的dispatchMessage方法:
public void dispatchMessage(Message msg) { if (msg.callback != null) { handleCallback(msg); } else { if (mCallback != null) { if (mCallback.handleMessage(msg)) { return; } } handleMessage(msg); } }既然是分发消息的方法,那必然会根据消息的类型做出不同的处理,这个方法正是根据Message对象是否携带了callback,如果携带了callback那就执行handleCallback方法,callback之前分析Message类的时候已经知道是一个Runnable的对象了。下面我们看看handleCallback是什么实现的:
private static void handleCallback(Message message) { message.callback.run(); }一目了然!直接调用callback的run方法。之前我们用post方法发送消息时携带的Runnable对象在Handle内部被转化为一个Message:
private static Message getPostMessage(Runnable r) { Message m = Message.obtain(); m.callback = r; return m; }
public interface Callback { public boolean handleMessage(Message msg); }
---------------------------------------------------------------------------------------
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。