Handler的消息循环涉及的类:Handler,Looper,Message,MessageQueue
创建
-
ActivityThread main方法中创建 Looper
public static void main(String[] args) { Looper.prepareMainLooper(); ... Looper.loop(); }
-
Looper prepare 方法中,通过 ThreadLocal 将 Looper 和 主线程进行绑定
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)); }
-
Looper 的私有化构造方法中 绑定了 MessageQueue
private Looper(boolean quitAllowed) { mQueue = new MessageQueue(quitAllowed); mThread = Thread.currentThread(); }
发送一个Message的流程
-
初始化Handler,获取并绑定当前线程的 MessageQueue 和 Looper,可以看到这个方法中有一个异常,如果是异步线程的话需要先调用 Looper.prepare()。
public Handler(Callback callback, boolean async) { ... mLooper = Looper.myLooper(); if (mLooper == null) { throw new RuntimeException( "Can't create handler inside thread " + Thread.currentThread() + " that has not called Looper.prepare()"); } mQueue = mLooper.mQueue; mCallback = callback; ... }
-
发送消息最终都会调用到 Handler.enqueueMessage(MessageQueue, Message, updateTime) 方法
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) { // 这里将当前的 Message 和 Handler 绑定 msg.target = this; if (mAsynchronous) { msg.setAsynchronous(true); } return queue.enqueueMessage(msg, uptimeMillis); }
-
将当前Message 放入 MessageQueue,如果队列中没有消息,直接将这个消息放在队首,如果队列中有消息,根据这个消息的接收处理时间,将其插入到合适的位置。
boolean enqueueMessage(Message msg, long when) { ... synchronized (this) { if (mQuitting) { IllegalStateException e = new IllegalStateException( msg.target + " sending message to a Handler on a dead thread"); Log.w(TAG, e.getMessage(), e); msg.recycle(); return false; } msg.markInUse(); msg.when = when; Message p = mMessages; boolean needWake; 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; } // We can assume mPtr != 0 because mQuitting is false. if (needWake) { nativeWake(mPtr); } } return true; }
消费消息
-
主线程初始化的时候有这样一段代码,将主线程绑定一个Looper,然后调用了 Looper.loop 方法轮询消息队列
public static void main(String[] args) { Looper.prepareMainLooper(); ... Looper.loop(); }
-
Looper.loop() 初始化主线程时,开启了消息循环,通过 MessageQueue 的 next 方法获取下一个消息,最终调用了 msg.target.dispatchMessage(msg); 将消息分发出去处理。处理玩这个消息后,调用 msg.recycleUnchecked() 这个方法,将它重新放回 消息池 中
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; ... for (;;) { Message msg = queue.next(); // might block if (msg == null) { // No message indicates that the message queue is quitting. return; } ... try { msg.target.dispatchMessage(msg); dispatchEnd = needEndTime ? SystemClock.uptimeMillis() : 0; } finally { if (traceTag != 0) { Trace.traceEnd(traceTag); } } ... msg.recycleUnchecked(); } }
-
MessageQueue 中轮询下一个消息的方法,这里Message 有一个回收池,只会获取到最新的 Message,将当前的 Message 取出,并且 next 设置为null,同事将 mMessages 指向其下一个 Message。
Message next() { ... 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 (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; } ... } }
-
调用 msg.target.dispatchMessage(msg); 去分发处理这个消息,其中 target 就是 Handler,最终调用的是 Handler 的 dispatchMessage 的方法
public void dispatchMessage(Message msg) { if (msg.callback != null) { handleCallback(msg); } else { if (mCallback != null) { // handleMessage 这两个方法都需要 Handler 去实现, //都是重写方法,理论上不会同时存在 if (mCallback.handleMessage(msg)) { return; } } handleMessage(msg); } } private static void handleCallback(Message message) { // callback 就是 Runnable 这个就能实现子线程 Runnable 中的代码 最终在主线程中执行 message.callback.run(); }
为什么不能在子线程创建 Handler
-
可以看到 Handler 初始化的时候 有这样一句代码:Looper.myLooper();
public Handler(Callback callback, boolean async) { ... mLooper = Looper.myLooper(); if (mLooper == null) { throw new RuntimeException( "Can't create handler inside thread " + Thread.currentThread() + " that has not called Looper.prepare()"); } mQueue = mLooper.mQueue; mCallback = callback; ... } public static @Nullable Looper myLooper() { return sThreadLocal.get(); }
并且在 消息系统初始化的时候有这样一段代码
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)); }
我们可以知道 sThreadLocal 是 ThreadLocal 的一个实例,他实际上是一个 Map,Thread 作为它的 Key,Looper 作为他的 value。
其中 Thread 是通过 Thread.currentThread() 获取的,直接在子线程中创建Handler,调用了 sThreadLocal.get() 的方法,此时返回的一定为 null,会抛出异常。所以需要先调用 Looper.prepare() 方法,给当前线程创建一个 Looper。
其中 Thread 中维护了一个 ThreadLocalMap,每次创建的 ThreadLocalMap,最终是被 Thread 持有的,真正的 Key value 存ThreadLocalMap里,而且这个 的 key 是通过一个弱引用持有的,所以当前线程执行完毕后,回收就回收了,不会继续持有当前的 Thread,不会造成内存泄漏。ThreadLocal只是 Thread 和 ThreadLocalMap 的操作类。
View.post 和 Handler.post 的区别
textView.setText 只能在主线程执行么
ThreadLocal 的用法和原理