在Android学习中Handler是很重要的一部分,个人觉得这个东西类似于WTL或者MFC中的消息映射的机制,搞过Windows开发的朋友理解起来应该很得心应手。在这里不得不说一句,个人感觉android的这套消息响应机制应该是模仿Windows的。程序的整体的结构和MFC也很是相像。
在google官方文档中说Handler是用来给进程发消息用的,每个Handler和一个线程还有他的消息队列相关联。当创建一个Handler的时候绑定于他所在线程的消息队列。
文档说的很明白,但是如何实现的呢?让我们用代码来说话。
众所周知当我们使用Handler的时候应该这样写:
public Handler mHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case FIRST_VIEW:
//....
break;
case SECOND_VIEW:
//....
break;
case THIRD_VIEW:
//....
break;
default:
break;
}
}
};
在Handler的构造函数中做了如下操作:
public Handler() {
this(null, false);
}
public Handler(Callback callback, boolean async) {
if (FIND_POTENTIAL_LEAKS) {
final Class<? extends Handler> klass = getClass();
if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
(klass.getModifiers() & Modifier.STATIC) == 0) {
Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
klass.getCanonicalName());
}
}
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;
}
该线程的looper是通过
Looper.myLooper();
获取到的
mLooper代码如下:
public static Looper myLooper() {
return sThreadLocal.get();
}
而sTreadLocal定义如下:
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
这个对象的定义采用了TLS这种技术,保证了每个线程在使用looper的时候都有他自己的looper。
当我们用Handler调用sendMessage或者post这类接口的时候会最终都会调到和该线程相关的Looper的mQueue对象的final boolean enqueueMessage(Message msg, long when)方法,在这里会将该msg放到对应线程的消息队列里。
final boolean enqueueMessage(Message msg, long when) {
if (msg.isInUse()) {
throw new AndroidRuntimeException(msg + " This message is already in use.");
}
if (msg.target == null) {
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 {
// Inserted within the middle of the queue. Usually we don't have to wake
// up the event queue unless there is a barrier at the head of the queue
// and the message is the earliest 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;
}
}
if (needWake) {
nativeWake(mPtr);
}
return true;
}
调试的时候我们可以将Android开放的源码Attach到工程中,这样对于学习很有帮助: