Handler的原理涉及到了几个重要对象:
Looper、MessageQueue、Message、Handler。
1、Looper用于轮询消息
2、MessageQueue消息队列:存消息
3、Message:消息对象
4、Handler:发送消息和处理消息
处理消息的步骤:
- 创建Looper并把Looper设置到当前线程,在创建Looper的同时创建MessageQueue
Looper.prepareMainLooper();
private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper(quitAllowed));
}
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
- 调用 Looper.loop();轮询消息
Looper.loop();
- 从MessageQueue中取出消息,并调用 msg.target.dispatchMessage(msg);把消息分发出去
当前的 msg.target就是Handler对象
for (;;) {
Message msg = queue.next(); // might block
if (msg == null) {
// No message indicates that the message queue is quitting.
return;
}
msg.target.dispatchMessage(msg);
- 调用Handler中的handleMessage处理消息
/**
* Handle system messages here.
*/
public void dispatchMessage(@NonNull Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
发送消息的步骤:
- 调用enqueueMessage把消息压入到消息队列中。
这里要注意的是,不仅是哪一种发消息的方式最后都会调用enqueueMessage,把消息压入到消息队列。并且消息中会把当前Handler对象也携带过去。msg.target = this;消息队列MessageQueue就是当前线程Looper中的MessageQueue。这里就可以确保这里的Looper、MessageQueue、Handler都是在同一个线程中的。
private boolean enqueueMessage(@NonNull MessageQueue queue, @NonNull Message msg,
long uptimeMillis) {
msg.target = this;
msg.workSourceUid = ThreadLocalWorkSource.getUid();
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
网友评论