Android 消息机制之 MessageQueue 消息队列
概述
Android 消息机制主要指的是 Handler 的运行机制及其所依赖的 MessageQueue 和 Looper 的工作过程,Handler、MessageQueue、Looper组成一个相互联系的整体。本文先从 MessageQueue 的源码来说明其实现原理。
MessageQueue 原理
MessageQueue ,顾名思义,意为消息队列,其操作主要有插入和读取。插入对应的方法为 enqueueMessage()
,即往消息队列中插入一条消息,而读取对应next()
,该方法会从消息队列中取出一条消息并将其从消息队列中删除。虽然 MessageQueue 的名字包含队列(Queue),但是其底层实现采用的是单链表,这是因为链表在插入和删除方面的性能好。下面看其源码实现。
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");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.nextprev.next = msg;}// We can assume mPtr != 0 because mQuitting is false.if (needWake) {nativeWake(mPtr);}}return true;}
enqueueMessage()中,Message 对象 p 代表下一个消息,对于新进来的消息,如果满足条件: p == null || when == 0 || when < p.when
,那么就将它插在消息列表的最前面;否则,就按照消息触发的时间( when 字段)来插入消息。也就是说,消息的插入是按照时间顺序从小到大进行的。
接下来在看看获取消息的 next()
方法:
Message next() .....//省略int pendingIdleHandlerCount = -1; // -1 only during first iteration// 1.如果nextPollTimeoutMillis=-1,一直阻塞不会超时。// 2.如果nextPollTimeoutMillis=0,不会阻塞,立即返回。// 3.如果nextPollTimeoutMillis>0,最长阻塞nextPollTimeoutMillis毫秒(超时)// 如果期间有程序唤醒会立即返回。int nextPollTimeoutMillis = 0;//死循环,但是拿到消息就return了for (;;) {if (nextPollTimeoutMillis != 0) {Binder.flushPendingCommands();}// 重要:调用到底层native的 MessageQueue// nextPollTimeoutMillis为-1,说明没有消息需要处理,在 native 中阻塞,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;//如果target==null,那么它就是屏障,需要循环遍历,一直往后找到第一个异步的消息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) {//如果有消息需要处理,先判断时间有没有到,如果没到的话设置一下阻塞时间,//场景如常用的postDelayif (now < msg.when) {//计算出离执行时间还有多久赋值给nextPollTimeoutMillis,//表示nativePollOnce方法要等待nextPollTimeoutMillis时长后返回,nextPollTimeoutMillis 不为 -1nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);} else {// 获取到消息mBlocked = false;//链表操作,获取msg并且删除该节点 if (prevMsg != null) prevMsg.next = msg.next;} else {mMessages = msg.next;}msg.next = null;msg.markInUse();//返回拿到的消息return msg;}} else {//没有消息,nextPollTimeoutMillis复位nextPollTimeoutMillis = -1;}.....//省略}
先说一下,MessageQueue 的数据结构为一个单向链表,Message 对象有个 next 字段保存列表中的下一个,MessageQueue 中的 mMessages 保存链表的第一个元素。
可以看到,next()
是一个无限循环的方法,读取消息时如果有消息就将该消息从消息列表中移除并返回该消息,否则就一直阻塞。
参考:
- 深入理解 MessageQueue
- Android多线程分析之四:MessageQueue的实现
- Android消息机制(二):Message和MessageQueue
Android 消息机制之 MessageQueue 消息队列相关推荐
- Unity中简单粗暴的消息机制(可限制消息调用次数)
上代码 /********************************************************文件: EasyMsg.cs作者: 阿飞日期: 2022年02月15日_09: ...
- Android的消息机制: Message/MessageQueue/Handler/Looper
概览 * Message:消息.消息里面可包含简单数据.Object和Bundle,还可以包含一个Runnable(实际上可看做回调). * MessageQueue:消息队列,供Looper线程消费 ...
- 安卓 Handler 消息机制之MessageQueue源码
首先,MessageQueue是属于底层类且它依附于创建他的Looper,除Looper外其他类无法单独创建他,如果要使用他,只能从Looper出获得. 下面将从几方面分析: 1. 消息队列存储原理 ...
- odoo14 mail.thread邮件消息机制(发送消息、字段变化跟踪记录)mail.activity.mixin安排活动
odoo内部的消息机制是十分便捷的,可以使用odoo 系统消息进行沟通,也可以通过odoo代发邮件进行沟通. 通过点击系统右上角的用户名,在弹出的下拉框中选择 '首选项' ,我们可以设置email选项 ...
- 【Android 异步操作】Handler 机制 ( MessageQueue 消息队列的阻塞机制 | Java 层机制 | native 层阻塞机制 | native 层解除阻塞机制 )
文章目录 一.MessageQueue 的 Java 层机制 二.MessageQueue 的 native 层阻塞机制 三.MessageQueue 的 native 层解除阻塞机制 三.Messa ...
- 【Android 异步操作】手写 Handler ( 消息队列 MessageQueue | 消息保存到链表 | 从链表中获取消息 )
文章目录 一.MessageQueue 消息队列存储消息 二.MessageQueue 消息队列取出消息 三.消息队列完整代码 一.MessageQueue 消息队列存储消息 Message 链表 : ...
- Android:Handler的消息机制
前言 Android 的消息机制原理是Android进阶必学知识点之一,在Android面试也是常问问题之一.在Android中,子线程是不能直接操作View,需要切换到主线程进行.那么这个切换动作就 ...
- android handler的机制和原理_一文搞懂handler:彻底明白Android消息机制的原理及源码
提起Android消息机制,想必都不陌生.其中包含三个部分:Handler,MessageQueue以及Looper,三者共同协作,完成消息机制的运行.本篇文章将由浅入深解析Android消息机制的运 ...
- Android Handler消息机制源码解析
好记性不如烂笔头,今天来分析一下Handler的源码实现 Handler机制是Android系统的基础,是多线程之间切换的基础.下面我们分析一下Handler的源码实现. Handler消息机制有4个 ...
- 【安卓学习笔记】Android Handler 消息机制探究
一.概述 1.android消息机制的含义: Android消息机制,其实指的就是 Handler 的运行机制,而 Handler 要正常运作,又需要底层的 MessageQueue , Looper ...
最新文章
- am大学计算机科学,德克萨斯AM大学TAMU(Texas AM University )计算机科学Computer Science专业排名第201-250位(2021年THE世界大学商科排名)...
- mysql auto position_MHA-Failover(GTID,Auto_Position=0)
- elasticsearch 随笔
- 计算机考试数据库相关知识点,计算机等级考试四级数据库工程师知识点总结
- cocos creator 打包apk_Cocos Creator Android打包 apk
- 将联系人信息导出为CSV和VCF格式文件
- 基于用户喜好以及电影类型的电影推荐算法
- 为什么每天那么累?如何让自己精力充沛?
- 【NVivo教程】使用Nvivo扩展文献综述
- NASA官网信息导航(愚见)
- Delphi历史版本介绍(二)从Delphi8到DelphiXE3
- 【DeeplabV3+ MIoU】DeeplabV3+计算评价指标
- 【深度学习BookNote】多层感知器(multi-layer perceptron)
- 微信转账一次显示两个_微信转账又出新玩法!同时满足两个条件,收款转账畅通无阻...
- postgresql启动流程之信号初始化
- mysql计算年龄_MySQL根据出生日期计算年龄的三种方法比较
- 腾讯运维专家的自我修养
- 记录学习技巧--如何翻阅或学习英文文档
- css的scal()函数使用
- Linux、UNIX 下磁带机设备(Tape)的管理和使用