Handler-Message-Looper源码研习
内容提要
这篇文章介绍了Android中的Handler、Looper和MessageQueue的工作原理。Handler用于发送和处理消息,Looper用于循环处理消息队列,MessageQueue用于存储消息。文章详细解释了Handler的构造函数、发送消息的方法,以及如何处理消息。同时还介绍了Looper的构造函数和获取Looper实例的方法。最后,文章还提到了使用epoll和eventfd实现Handler机制的底层逻辑。
延伸解读
异步消息与同步屏障的协作机制
文章指出,Handler 支持异步消息,异步消息不受同步屏障影响。同步屏障通过 postSyncBarrier 插入一个 target 为 null 的消息,阻止后续同步消息执行,直到 removeSyncBarrier 移除屏障。异步消息则能绕过屏障继续处理。这种机制常用于 UI 绘制等需要优先处理异步任务的场景,但需注意屏障必须成对使用,否则会导致队列阻塞。
Message 复用池的设计与使用建议
Message 内部维护一个静态池(sPool),通过 obtain() 方法复用实例,避免频繁创建对象。池大小上限为 50,当池空时才会新建。复用后的 Message 会重置 flags 等状态。开发者应优先使用 obtain() 而非 new Message(),以减少内存分配和 GC 压力。同时,消息被回收后不应再修改其内容,否则可能引发状态错误。
Native 层 epoll 与 eventfd 的阻塞唤醒原理
MessageQueue 的阻塞与唤醒依赖 Native 层的 epoll 和 eventfd。当队列为空时,nativePollOnce 通过 epoll_wait 进入休眠,释放 CPU;当有新消息入队时,enqueueMessage 调用 nativeWake,向 eventfd 写入数据,唤醒 epoll_wait。这种机制实现了高效的生产者-消费者模型,确保线程在无消息时休眠,有消息时及时响应。
Looper 死循环与消息分发流程
Looper.loop() 启动一个死循环,不断调用 MessageQueue.next() 获取消息。next() 可能阻塞,直到有消息或超时。获取到消息后,通过 msg.target.dispatchMessage(msg) 回调到 Handler 进行分发。分发时优先处理 Message 的 callback(即 post 的 Runnable),其次处理 Handler 的 mCallback,最后调用 handleMessage。处理完毕后,消息被回收,循环继续。
Q&A
Handler在Android中有什么作用?
Handler用于发送和处理消息,帮助实现线程间的通信。
Looper是如何与Handler关联的?
Looper通过注入实例到Handler的构造函数中,将Handler与Looper绑定。
MessageQueue的enqueueMessage方法有什么作用?
enqueueMessage方法用于将消息插入到消息队列中,并处理消息的状态标志。
Looper的循环处理机制是怎样的?
Looper通过死循环不断获取和消费消息,确保消息的处理。
如何发送异步消息?
可以通过Handler的sendMessage方法,并设置async参数为true来发送异步消息。
epoll和eventfd在Handler机制中有什么作用?
epoll和eventfd用于实现高效的I/O多路复用和事件通知,支持Handler机制的底层逻辑。