Handler MessageQueue Runnable 与 Looper
runable 和 message 可以被压入某个MessageQueue中
Looper循环的去做某件事,不断从MessageQueue中取出一个item,然后传递给handler进行处理。
Handler真正“处理事情”的地方
总结来说就是Looper不断获取MessageQueue中的一个Message,然后由Handler来处理。
Handler源码
每个Thread只对应一个Looper
每个Looper只对应一个MessageQueue
每个MessageQueue中有N个Message
每个Message中最多指定一个Handler来处理事件
Handler的功能
1.处理Messgae
public void dispatchMessage(Message msg)
public void handleMessage(Message msg)
Looper从MessageQueue中取一个Message后,首先会调用Handler.dispatchMessage()进行消息的派发。
首先判断msg.callback是否为null,不为空的情况下将优先通过callback来处理
判断Handler mCallback是否为空,在不为空的情况下,调用mCallback.handleMessage
如果前面两个对象都不存在那么调用,Handler.handlerMessage。
handlerMessage把Message塞入MessageQueue中。
post系列和send系列
send系列直接处理message
post系列把零散的信息组装成message后发送。
MessageQueue
是一个native方法的队列 包含这些本地方法
private native static long nativeInit(); 初始化队列
private native static void nativeDestroy(long ptr); 销毁队列
private native void nativePollOnce(long ptr, int timeoutMillis); /*non-static for callbacks*/
private native static void nativeWake(long ptr);
private native static boolean nativeIsPolling(long ptr);
private native static void nativeSetFileDescriptorEvents(long ptr, int fd, int events);
Looper
Looper分为主线程和普通线程
主线程为ActivityThread
普通线程如下
Looper.prepare();
ThreadLocal是一个特殊的全局变量,只限定于当前线程所处的线程。sThreadLocal保存了新创建的Looper对象
Handler
handler有多种创建函数
public Handler();
public Handler(CallBack callback);
public Handler(Looper looper);
public Handler(Looper looper,Callback callback);
需要初始化的变量为:
MessageQueue mQueue;
Looper mLooper;
Callback mCallback;
通过以上的mQueue和Looper的mQueue关联,Looper处理到这一情况又会从中调用Handler来进行处理。
ActivityThread
主线程调用的是Looper.prepareMainLooper()和Looper.prepare()
主线程绑定的是ActivityThread.getHandler() 返回的是成员变量mH(Hanlder)
Looper.loop函数
loop函数会一直通过一个死循环一直从MessageQueue中拿消息(通过函数queue.next())。如果消息为null 就返回结束任务,如果有消息来那就分发到handler中处理消息。
next函数如下
Message next() {
// Return here if the message loop has already quit and been disposed.
// This can happen if the application tries to restart a looper after quit
// which is not supported.
final long ptr = mPtr;
if (ptr == 0) {
return null;
}
int pendingIdleHandlerCount = -1; // -1 only during first iteration
int nextPollTimeoutMillis = 0;
for (;;) {
if (nextPollTimeoutMillis != 0) {
Binder.flushPendingCommands();
}
nativePollOnce(ptr, nextPollTimeoutMillis);
synchronized (this) {
// Try to retrieve the next message. Return if found.
final long now = SystemClock.uptimeMillis();
Message prevMsg = null;
Message msg = mMessages;
if (msg != null && msg.target == null) {
// Stalled by a barrier. Find the next asynchronous message in the queue.
do {
prevMsg = msg;
msg = msg.next;
} while (msg != null && !msg.isAsynchronous());
}
if (msg != null) {
if (now < msg.when) {
// Next message is not ready. Set a timeout to wake up when it is ready.
nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
} else {
// Got a message.
mBlocked = false;
if (prevMsg != null) {
prevMsg.next = msg.next;
} else {
mMessages = msg.next;
}
msg.next = null;
if (DEBUG) Log.v(TAG, "Returning message: " + msg);
msg.markInUse();
return msg;
}
} else {
// No more messages.
nextPollTimeoutMillis = -1;
}
// Process the quit message now that all pending messages have been handled.
if (mQuitting) {
dispose();
return null;
}
// If first time idle, then get the number of idlers to run.
// Idle handles only run if the queue is empty or if the first message
// in the queue (possibly a barrier) is due to be handled in the future.
if (pendingIdleHandlerCount < 0
&& (mMessages == null || now < mMessages.when)) {
pendingIdleHandlerCount = mIdleHandlers.size();
}
if (pendingIdleHandlerCount <= 0) {
// No idle handlers to run. Loop and wait some more.
mBlocked = true;
continue;
}
if (mPendingIdleHandlers == null) {
mPendingIdleHandlers = new IdleHandler[Math.max(pendingIdleHandlerCount, 4)];
}
mPendingIdleHandlers = mIdleHandlers.toArray(mPendingIdleHandlers);
}
// Run the idle handlers.
// We only ever reach this code block during the first iteration.
for (int i = 0; i < pendingIdleHandlerCount; i++) {
final IdleHandler idler = mPendingIdleHandlers[i];
mPendingIdleHandlers[i] = null; // release the reference to the handler
boolean keep = false;
try {
keep = idler.queueIdle();
} catch (Throwable t) {
Log.wtf(TAG, "IdleHandler threw exception", t);
}
if (!keep) {
synchronized (this) {
mIdleHandlers.remove(idler);
}
}
}
// Reset the idle handler count to 0 so we do not run them again.
pendingIdleHandlerCount = 0;
// While calling an idle handler, a new message could have been delivered
// so go back and look again for a pending message without waiting.
nextPollTimeoutMillis = 0;
}
}