概述

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 消息队列相关推荐

  1. Unity中简单粗暴的消息机制(可限制消息调用次数)

    上代码 /********************************************************文件: EasyMsg.cs作者: 阿飞日期: 2022年02月15日_09: ...

  2. Android的消息机制: Message/MessageQueue/Handler/Looper

    概览 * Message:消息.消息里面可包含简单数据.Object和Bundle,还可以包含一个Runnable(实际上可看做回调). * MessageQueue:消息队列,供Looper线程消费 ...

  3. 安卓 Handler 消息机制之MessageQueue源码

    首先,MessageQueue是属于底层类且它依附于创建他的Looper,除Looper外其他类无法单独创建他,如果要使用他,只能从Looper出获得. 下面将从几方面分析: 1. 消息队列存储原理 ...

  4. odoo14 mail.thread邮件消息机制(发送消息、字段变化跟踪记录)mail.activity.mixin安排活动

    odoo内部的消息机制是十分便捷的,可以使用odoo 系统消息进行沟通,也可以通过odoo代发邮件进行沟通. 通过点击系统右上角的用户名,在弹出的下拉框中选择 '首选项' ,我们可以设置email选项 ...

  5. 【Android 异步操作】Handler 机制 ( MessageQueue 消息队列的阻塞机制 | Java 层机制 | native 层阻塞机制 | native 层解除阻塞机制 )

    文章目录 一.MessageQueue 的 Java 层机制 二.MessageQueue 的 native 层阻塞机制 三.MessageQueue 的 native 层解除阻塞机制 三.Messa ...

  6. 【Android 异步操作】手写 Handler ( 消息队列 MessageQueue | 消息保存到链表 | 从链表中获取消息 )

    文章目录 一.MessageQueue 消息队列存储消息 二.MessageQueue 消息队列取出消息 三.消息队列完整代码 一.MessageQueue 消息队列存储消息 Message 链表 : ...

  7. Android:Handler的消息机制

    前言 Android 的消息机制原理是Android进阶必学知识点之一,在Android面试也是常问问题之一.在Android中,子线程是不能直接操作View,需要切换到主线程进行.那么这个切换动作就 ...

  8. android handler的机制和原理_一文搞懂handler:彻底明白Android消息机制的原理及源码

    提起Android消息机制,想必都不陌生.其中包含三个部分:Handler,MessageQueue以及Looper,三者共同协作,完成消息机制的运行.本篇文章将由浅入深解析Android消息机制的运 ...

  9. Android Handler消息机制源码解析

    好记性不如烂笔头,今天来分析一下Handler的源码实现 Handler机制是Android系统的基础,是多线程之间切换的基础.下面我们分析一下Handler的源码实现. Handler消息机制有4个 ...

  10. 【安卓学习笔记】Android Handler 消息机制探究

    一.概述 1.android消息机制的含义: Android消息机制,其实指的就是 Handler 的运行机制,而 Handler 要正常运作,又需要底层的 MessageQueue , Looper ...

最新文章

  1. am大学计算机科学,德克萨斯AM大学TAMU(Texas AM University )计算机科学Computer Science专业排名第201-250位(2021年THE世界大学商科排名)...
  2. mysql auto position_MHA-Failover(GTID,Auto_Position=0)
  3. elasticsearch 随笔
  4. 计算机考试数据库相关知识点,计算机等级考试四级数据库工程师知识点总结
  5. cocos creator 打包apk_Cocos Creator Android打包 apk
  6. 将联系人信息导出为CSV和VCF格式文件
  7. 基于用户喜好以及电影类型的电影推荐算法
  8. 为什么每天那么累?如何让自己精力充沛?
  9. 【NVivo教程】使用Nvivo扩展文献综述
  10. NASA官网信息导航(愚见)
  11. Delphi历史版本介绍(二)从Delphi8到DelphiXE3
  12. 【DeeplabV3+ MIoU】DeeplabV3+计算评价指标
  13. 【深度学习BookNote】多层感知器(multi-layer perceptron)
  14. 微信转账一次显示两个_微信转账又出新玩法!同时满足两个条件,收款转账畅通无阻...
  15. postgresql启动流程之信号初始化
  16. mysql计算年龄_MySQL根据出生日期计算年龄的三种方法比较
  17. 腾讯运维专家的自我修养
  18. 记录学习技巧--如何翻阅或学习英文文档
  19. css的scal()函数使用
  20. Linux、UNIX 下磁带机设备(Tape)的管理和使用

热门文章

  1. 赵荣人文地理学第2版笔记和课后答案
  2. 《软件测试》学习目标与计划
  3. 软考每日一练||网络工程师
  4. TTL转RS232电平转换电路及工作原理
  5. 2021 上半年软考软件设计师真题完整版
  6. Dreamweaver视频教程(共53课时)
  7. C#条形码图像生成库
  8. 如何计算机房负载,机房UPS电源实际负载容量与负载量是怎么计算的?
  9. Linux tty字符终端下VIM显示混乱的解决方法
  10. 计算机发展史 文档,计算机发展史课件