Handler/Looper/MessageQueue 源码深度解析
Android 主线程消息循环机制完全指南
目录
整体架构概览
Looper 初始化与消息循环
MessageQueue 消息队列原理
Message 消息机制
Handler 消息发送与处理
常见面试题解析
1. 整体架构概览 四大核心组件 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 ┌─────────────────────────────────────────────────────────────────────┐ │ Handler 消息机制 │ ├─────────────────────────────────────────────────────────────────────┤ │ │ │ ┌─────────┐ ┌─────────────┐ ┌──────────────┐ │ │ │ Handler │───▶│ MessageQueue │◀───│ Looper │ │ │ └─────────┘ └─────────────┘ └──────────────┘ │ │ │ │ │ │ │ ┌──────────┐ │ │ │ └─────────────▶│ Message │◀─────────────┘ │ │ └──────────┘ │ │ │ │ Handler: 发送和处理消息 │ │ Looper: 不断从 MessageQueue 取消息 │ │ MessageQueue: 消息队列(单链表实现) │ │ Message: 消息载体 │ │ │ └─────────────────────────────────────────────────────────────────────┘
主线程启动流程 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 public static void main (String[] args) { Looper.prepareMainLooper(); ActivityThread thread = new ActivityThread (); thread.attach(false ); Looper.loop(); throw new RuntimeException ("Main thread loop unexpectedly exited" ); }
2. Looper 初始化与消息循环 Looper.prepareMainLooper() 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 public static void prepareMainLooper () { if (sMainLooper != null ) { throw new RuntimeException ("Only one Looper may be created per thread" ); } sMainLooper = myLooper(); } private static void prepare (boolean quitAllowed) { if (sThreadLocal.get() != null ) { throw new RuntimeException ("Only one Looper per thread" ); } sThreadLocal.set(new Looper (quitAllowed)); }
Looper.loop() - 核心方法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 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; Binder.clearCallingIdentity(); final long ident = Binder.clearCallingIdentity(); for (;;) { Message msg = queue.next(); if (msg == null ) { return ; } msg.target.dispatchMessage(msg); msg.recycleUnchecked(); } }
关键点:为什么不会 ANR? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 ┌─────────────────────────────────────────────────────────────────────┐ │ Looper.loop() 不会 ANR │ ├─────────────────────────────────────────────────────────────────────┤ │ │ │ ANR 发生条件:主线程阻塞 > 5 秒处理消息 │ │ │ │ Looper.loop() 本质: │ │ 1. queue.next() - 获取消息(可阻塞) │ │ 2. msg.target.dispatchMessage() - 处理消息(通常很快) │ │ 3. 回到步骤 1 │ │ │ │ 关键:处理每条消息的时间很短,不会长时间阻塞 │ │ 如果处理耗时,应该在子线程执行或使用 AsyncTask │ │ │ └─────────────────────────────────────────────────────────────────────┘
3. MessageQueue 消息队列原理 MessageQueue 初始化 1 2 3 4 5 6 MessageQueue(boolean quitAllowed) { mQuitAllowed = quitAllowed; mPtr = nativeInit(); }
next() - 获取下一条消息 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 Message next () { for (;;) { if (nextPollTimeoutMs != 0 ) { Binder.flushPendingCommands(); } nativePollOnce(mPtr, nextPollTimeoutMs); synchronized (this ) { final long now = SystemClock.uptimeMillis(); Message prevMsg = null ; Message msg = mMessages; if (msg != null && msg.target == null ) { do { prevMsg = msg; msg = msg.next; } while (msg != null && !msg.isAsynchronous()); } if (msg != null ) { if (now < msg.when ) { nextPollTimeoutMs = (int ) Math.min( msg.when - now, Integer.MAX_VALUE); } else { mMessages = msg.next; msg.next = null ; msg.markInUse(); return msg; } } else { nextPollTimeoutMs = -1 ; } if (mQuitting) { dispose(); return null ; } } } }
同步屏障 (Sync Barrier) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 public int postSyncBarrier (long when ) { synchronized (this ) { final int token = mNextBarrierToken++; final Message msg = Message.obtain(); msg.markInUse(); msg.when = when ; msg.arg1 = token; msg.target = null ; } } public void removeSyncBarrier (int token) { synchronized (this ) { } }
同步屏障的作用 :优先执行异步消息,用于 View 的 invalidate 等紧急绘制操作。
4. Message 消息机制 Message 对象池 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 public final class Message implements Parcelable { private static final Object sPoolSync = new Object (); private static Message sPool; private static int sPoolSize = 0 ; private static final int MAX_POOL_SIZE = 50 ; public static Message obtain () { synchronized (sPoolSync) { if (sPool != null ) { Message m = sPool; sPool = m.next; m.next = null ; m.flags = 0 ; sPoolSize--; return m; } } return new Message (); } void recycleUnchecked () { flags = 0 ; what = 0 ; arg1 = 0 ; arg2 = 0 ; obj = null ; replyTo = null ; sendingUid = -1 ; workSourceUid = 0 ; when = 0 ; target = null ; callback = Runnable; data = null ; synchronized (sPoolSync) { if (sPoolSize < MAX_POOL_SIZE) { next = sPool; sPool = this ; sPoolSize++; } } } }
Message 结构(单链表) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 public final class Message implements Parcelable { public int what; public int arg1; public int arg2; public Object obj; public long when ; public Handler target; public Runnable callback; Message next; static final int FLAG_IN_USE = 1 << 0 ; static final int FLAG_ASYNCHRONOUS = 1 << 1 ; int flags; }
1 2 3 4 5 6 7 Message 链表结构: mMessages ──▶ [when:100] ──▶ [when:200] ──▶ [when:300] ──▶ null │ │ │ ▼ ▼ ▼ msg1 msg2 msg3 (target) (target) (target)
5. Handler 消息发送与处理 Handler 构造 1 2 3 4 5 6 7 8 9 10 11 12 13 public Handler (Callback callback, boolean async) { 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; }
发送消息 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 public final boolean sendMessage (Message msg) { return sendMessageDelayed(msg, 0 ); } public final boolean sendMessageDelayed (Message msg, long delayMillis) { if (delayMillis < 0 ) { delayMillis = 0 ; } return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis); } public boolean sendMessageAtTime (Message msg, long uptimeMillis) { MessageQueue queue = mQueue; if (queue == null ) { return false ; } msg.target = this ; return enqueueMessage(queue, msg, uptimeMillis); } private boolean enqueueMessage (MessageQueue queue, Message msg, long uptimeMillis) { msg.target = this ; if (mAsynchronous) { msg.setAsynchronous(true ); } return queue.enqueueMessage(msg, uptimeMillis); }
dispatchMessage - 消息分发 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 public void dispatchMessage (Message msg) { if (msg.callback != null ) { msg.callback.run(); return ; } if (mCallback != null ) { if (mCallback.handleMessage(msg)) { return ; } } handleMessage(msg); }
6. 常见面试题解析 Q1: Handler 发送的消息如何保证按时间顺序执行? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 boolean enqueueMessage(Message msg, long when ) { if (msg.target == null ) { throw new IllegalArgumentException("Message must have a target." ); } synchronized (this ) { if (msg.isInUse()) { throw new IllegalStateException(); } msg.markInUse(); msg.when = when ; msg.next = null ; Message p = mMessages; boolean needWake; if (p == null || when < p.when ) { msg.next = p; mMessages = msg; needWake = mBlocked; } else { Message prev; do { prev = p; p = p.next; } while (p != null && when >= p.when ); msg.next = p; prev.next = msg; needWake = false ; } if (needWake) { nativeWake(mPtr); } } return true ; }
Q2: 为什么主线程不会因为 loop() 死循环卡死? 1 2 3 4 5 答案: 1. loop() 不是 busy-wait,它会调用 nativePollOnce() 阻塞 2. 阻塞时线程不消耗 CPU 3. 当有消息到达时,Native 层会唤醒线程 4. 处理每条消息通常很快(<1ms),不会阻塞
Q3: Handler 如何切换线程? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 class WorkerThread : Thread () { lateinit var handler: Handler override fun run () { Looper.prepare() handler = Handler(Looper.myLooper()!!) { true } Looper.loop() } } workerThreadHandler.post { }
Q4: MessageQueue 的 idleHandler 什么时候执行? 1 2 3 4 5 6 7 8 9 10 11 12 13 public void addIdleHandler (IdleHandler handler) { synchronized (this ) { mIdleHandlers.add(handler); } } Looper.myQueue().addIdleHandler { performInitialization() false }
总结 1 2 3 4 5 6 7 8 9 10 11 Handler 机制核心流程: 1. 主线程创建 Looper.prepareMainLooper() 2. Looper 创建 MessageQueue 3. Looper.loop() 开启消息循环 4. Handler sendMessage() 将消息加入队列 5. MessageQueue.next() 返回待处理消息 6. Handler.dispatchMessage() 分发消息 7. 回调 handleMessage() 处理 8. 回收 Message 到对象池 9. 回到步骤 4
相关文章 :