简要分析android中消息循环涉及到的几个方法的源代码(API19):
1 Handler构造方法
public Handler(Callback callback, boolean async)
{
//检测Handler是否写成匿名内部类的形式,是则提示这有可能导致内存泄露
//如果Handler写成匿名内部类,当我们要销毁它的外部类对象(通常为Activity)时
//该外部类所处的线程中的messageQueue中的message持有handler,也就是匿名内部类对象本身的引用
//而匿名内部类持有外部类的引用
//如果messageQueue中有延迟时间很长的message,就会导致handler无法被销毁,进而导致外部类(Activity等)无法被销毁
//造成这个问题的本质原因是handler、looper、messageQueue是threadLocal设置的线程级变量
//其生命周期可能长于该线程中运行的Activity等外部类,而handler又被写成了内部类
//导致内部类的生命周期长于外部类,阻止了外部类的销毁
if (FIND_POTENTIAL_LEAKS){
final Class<? extendsHandler> klass = getClass();
if((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass())&&
(klass.getModifiers() &Modifier.STATIC) == 0) {
Log.w(TAG, "Thefollowing Handler class should be static or leaks might occur: " +
klass.getCanonicalName());
}
}
//取得当前线程的looper
mLooper = Looper.myLooper();
//当前线程没有looper则报错
if (mLooper == null) {
throw newRuntimeException(
"Can't create handlerinside thread that has not called Looper.prepare()");
}
//从当前线程的looper中取得MessageQueue的引用
mQueue = mLooper.mQueue;
mCallback = callback;
mAsynchronous = async;
//handler建立的时候就建立和取得了本线程的looper和messagequeue
}
2 Looper的myLooper()方法
public static Looper myLooper() {
//从当前looper的threadLocal线程本地变量中取出本线程拥有的looper
return sThreadLocal.get();
}
3 Looper的构造方法
//looper对象持有一个threadLocal对象,messageQueue
staticfinal ThreadLocal<Looper> sThreadLocal = newThreadLocal<Looper>();
private staticLooper sMainLooper;
finalMessageQueue mQueue;
finalThread mThread;
//Looper的构造方法是私有的,并且在构造的时候生成了MessageQueue
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}4 Looper的prepare()方法
//用该方法调用looper的构造方法创建looper
private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get()!= null) {
throw newRuntimeException("Only one Looper may be created per thread");
}
//创建新的looper对象存入当前looper的threadLocal线程本地变量
sThreadLocal.set(new Looper(quitAllowed));
//使用threadLocal对象存储looper保证了一个线程只有一个looper
//又因为message Queue是在looper的构造方法中建立的,一个looper只有一个messageQueue
//这样,线程、looper、messageQueue实现了一一对应
//但是,handler与上述三个部件不是一一对应的,一个线程的looper和messageQueue可以对应多个handler
}
5 Looper的loop()方法
//用该方法取得当前线程的looper并启动其消息循环
public static void loop() {
//取得当前线程的looper
final Looper me = myLooper();
if (me == null) {
throw newRuntimeException("No Looper; Looper.prepare() wasn't called on thisthread.");
}
//取得当前线程的MessageQueue
final MessageQueue queue = me.mQueue;
// Make sure the identity of thisthread is that of the local process,
// and keep track of what that identitytoken actually is.
Binder.clearCallingIdentity();
final long ident =Binder.clearCallingIdentity();
//开启一个死循环,从messageQueue中取出下一条消息,取出的动作可能是阻塞的
for (;;){
Message msg = queue.next(); // might block
if (msg == null) {
// No message indicates thatthe message queue is quitting.
return;
}
// This must be in a localvariable, in case a UI event sets the logger
Printer logging = me.mLogging;
if (logging != null){
logging.println(">>>>> Dispatching to " +msg.target + " " +
msg.callback + ": " +msg.what);
}
//将从messageQueue中取得的消息发送给该消息指定的handler去处理
msg.target.dispatchMessage(msg);
if (logging != null){
logging.println("<<<<< Finished to " +msg.target + " " + msg.callback);
}
// Make sure that during the courseof dispatching the
// identity of the thread wasn'tcorrupted.
final long newIdent =Binder.clearCallingIdentity();
if (ident != newIdent) {
Log.wtf(TAG,"Thread identity changed from 0x"
+ Long.toHexString(ident)+ " to 0x"
+ Long.toHexString(newIdent)+ " while dispatching to "
+msg.target.getClass().getName() + " "
+ msg.callback + "what=" + msg.what);
}
//handler处理完消息后将其回收
msg.recycle();
}
}
6 MessageQueue的的next()方法
//从messageQueue中取出下一个消息
Message next() {
......................
//在取消息时用同步锁锁住messageQueue,防止不同线程的 handler同时操作messageQueue
synchronized (this) {
// Try to retrieve the nextmessage. Return if found.
final long now =SystemClock.uptimeMillis();
Message prevMsg = null;
Message msg = mMessages;
//从前向后遍历链表,找到第一个异步(其它线程发来的)消息
if (msg != null && msg.target == null) {
// Stalled by abarrier. Find the next asynchronousmessage in the queue.
do {
prevMsg = msg;
msg = msg.next;
} while (msg != null &&!msg.isAsynchronous());
}
//由于messageQueue的enqueueMessage()方法在将message插入消息链表的时候根据消息的执行时间进行了排序
//所以之前找到的第一个异步消息一定是执行时间最早的异步消息
if (msg!= null) {
//如果当前时间早于执行时间最早的异步消息的执行时间,不执行
if (now < msg.when) {
// Next message is notready. Set a timeout to wake up when itis ready.
nextPollTimeoutMillis =(int) Math.min(msg.when - now, Integer.MAX_VALUE);
//如果当前时间晚于执行时间最早的异步消息的执行时间,返回这个异步消息给looper
} else {
// Got a message.
mBlocked = false;
if (prevMsg != null){
prevMsg.next =msg.next;
} else {
mMessages =msg.next;
}
msg.next = null;
if (false)Log.v("MessageQueue", "Returning message: " + msg);
msg.markInUse();
return msg;
}
} else {
// No more messages.
nextPollTimeoutMillis = -1;
}
................................
}
7 MessageQueue的enqueueMessage()方法
boolean enqueueMessage(Message msg, long when) {
if (msg.isInUse()) {
throw newAndroidRuntimeException(msg + " This message is already in use.");
}
if (msg.target == null) {
throw newAndroidRuntimeException("Message must have a target.");
}
synchronized (this) {
if (mQuitting) {
RuntimeException e = newRuntimeException(
msg.target + " sending messageto a Handler on a dead thread");
Log.w("MessageQueue",e.getMessage(), e);
return false;
}
msg.when = when;
Message p = mMessages;
boolean needWake;
//按照message自带的执行时间将message插入到消息链表中,执行时间早的插入到靠前的位置
if (p ==null || when == 0 || when < p.when) {
// New head, wake up the eventqueue if blocked.
msg.next = p;
mMessages = msg;
needWake = mBlocked;
} else {
// Inserted within the middleof the queue. Usually we don't have towake
// up the event queue unlessthere is a barrier at the head of the queue
// and the message is theearliest asynchronous message in the queue.
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;
}
// We can assume mPtr != 0 becausemQuitting is false.
if (needWake) {
nativeWake(mPtr);
}
}
return true;
}
8 Handler的dispatchMessage()方法
//looper调用handler的此方法,将messageQueue中取出的message传给此方法
//此方法按优先级依次查找三种方法来处理message,找到就结束,找不到再去找下一个优先级的方法
//优先级1:message自己指定的处理方法
//优先级2:handler在构造时传入的Handler.Callback接口的实现对象所重写的handleMessage()方法
//优先级3:handler被覆盖的handleMessage()方法
public void dispatchMessage(Message msg) {
if (msg.callback != null){
handleCallback(msg);
} else {
if (mCallback != null){
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
------------------------------------------------------我是分割线-----------------------------------------------------------------------------看过了上面几个跟消息循环有关的方法,我们可以总结一下一个消息从生到死的全过程啦:
消息循环流程:
0. Looper类中有一个静态成员变量threadLocal对象
1. Looper.prepare():
(Looper类的静态方法)
构造looper对象,looper对象在构造时构造messageQueue对象,
用Looper类的静态threadLocal对象将构造出来的looper对象设定为线程级变量
2. Handler handler = new Handler(){ @Override public void handleMessage(Messagemsg){.........}}
构造Handler继承类的对象,重写其handleMessage()方法
构造时调用Looper类的静态方法myLooper()从Looper类的静态threadLocal对象中取得当前线程所拥有的looper对象
此时handler拥有了当前线程的looper和messageQueue对象
3. Looper.loop()
(Looper类的静态方法)
调用Looper类的静态方法myLooper()从Looper类的静态threadLocal对象中取得当前线程所拥有的looper对象,
开启死循环不停地调用messageQueue的next()方法以阻塞方式从刚才取得的looper对象中包含的messageQueue中获取下一个message
将获取的message传给message的target所指定的handler的dispatchMessage()方法
后者依据优先级调用Handler.Callback或者handler类方法的handleMessage()来处理消息
4. handler.sendMessage(Message msg):
将传入message的target设定成自己
调用当前线程的messageQueue的enqueueMessage()方法将传入的message按照message执行时间先后顺序插入messageQueue
5. 第3步和第4步同时进行
handler.sendMessage(Messagemsg)通过调用messageQueue的enqueueMessage()将消息加入消息队列
Looper.loop()通过messageQueue的next()方法将消息从消息队列中取出,发给其指定的handler的handleMessage()方法处理