当前位置: 首页 > news >正文

从 C 链表到 Android Looper:MessageQueue 的底层原理一条线讲透

前言:为什么要从 C 链表讲起?

很多 Android 开发者都用过Handler / Looper / MessageQueue
但一深入源码就会觉得“抽象、复杂、难以下手”。

其实问题不在 Android,而在于我们没把底层模型串起来

如果你愿意退回一步,用C 语言最基础的数据结构视角去看,就会发现:

Android 的消息机制,本质就是:
链表 + 队列 + 排序 + 阻塞循环。

本文尝试做一件事:
👉从 C 语言的链表出发,一步一步推导到 Android 的 MessageQueue / Looper
把这条逻辑链完整走一遍。

一、指针的本质:一切从“地址”开始

在 C 语言中:

int x = 10; int *p = &x;
  • x是一个值
  • &x是 x 的内存地址
  • p是一个存地址的变量
  • *p表示“通过地址访问那块内存里的值”

指针 = 存地址的变量

这是后面所有数据结构的根基。

这一点非常重要,因为:

  • 链表
  • 队列
  • MessageQueue
  • Looper

全部建立在“地址关系”之上。

二、为什么需要 struct?

单个变量无法表达复杂对象,我们需要把“相关数据”组织在一起:

struct Person { int age; int height; };

struct的本质只是:
👉一块内存的布局说明书

它本身并不负责逻辑。

三、Node:链表的最小原子结构

链表的核心是Node

typedef struct Node { void *data; // 指向真实数据 struct Node *next; // 指向下一个节点 } Node;

这里有两个完全不同层次的指针:

  • data业务数据指针

  • next结构关系指针

一句话总结:

Node = 数据 + 指向下一个 Node 的关系

多个 Node 通过next串起来,就形成了链表:

Node1 -> Node2 -> Node3 -> NULL

四、为什么“只有 Node”是没用的?

此时会遇到一个致命问题:

👉从哪里开始遍历?

链表必须有一个“入口”,也必须有人维护整体状态。

五、Queue:Node 的管理者(系统思维的起点)

于是我们引入“管理结构”:

typedef struct { Node *head; Node *tail; int size; } Queue;

现在结构关系变成:

Queue ├── head ──> Node ──> Node ──> Node ──> NULL ├── tail ────────────────────────────┘ └── size

注意一个非常重要的事实:

Queue 自己不存数据,它只负责“管理 Node 的关系”。

这是从“数据结构”走向“系统设计”的第一步。

六、为什么Queue*不需要二级指针?

初始化 Queue 通常这样写:

Queue q; queue_init(&q);
void queue_init(Queue *q) { q->head = NULL; q->tail = NULL; q->size = 0; }

这里:

  • q本体已经存在(在栈上)

  • 函数只是修改Queue内部字段

  • 并没有修改指针变量本身

所以:
👉一级指针足够

七、什么时候才需要二级指针?

只有一种情况:

当函数需要“创建 / 替换一个指针变量本身”

void create_queue(Queue **pq) { *pq = malloc(sizeof(Queue)); }

调用方式:

Queue *q = NULL; create_queue(&q);

这里的本质是:

  • q是一个Queue*指针变量

  • &q的类型是Queue**

  • Queue**正好能“接住”&q

  • *pq = malloc(...)本质是给q重新赋值

👉二级指针的本质是“类型匹配 + 写回指针变量”

八、从 Queue 到 MessageQueue:关键差异只有一个

普通 Queue 是FIFO

Android 的 MessageQueue 不一样,它是:

按执行时间排序的消息队列

因此 Node 演化为 Message:

typedef struct Message { long when; // 什么时候执行 void (*callback)(void); // 要执行的任务 struct Message *next; } Message;

你会发现:

  • 结构没变

  • 指针没变

  • 只是数据字段更“业务化”

九、MessageQueue 的核心职责

MessageQueue 主要做三件事:

  1. when有序插入 Message

  2. 维护单向链表

  3. 提供next()获取“当前可执行的消息”

它不是简单的队列,而是“时间有序链表”。

十、Looper:系统的“心跳循环”

Looper 的逻辑可以简化成一句话:

for (;;) { Message *msg = queue.next(); dispatch(msg); }

也就是说:

Looper = 无限循环 + 从 MessageQueue 取消息并执行

这就是 Android UI 线程的“发动机”。

十一、为什么 Looper 不会空转卡死?

关键在MessageQueue.next()

  • 如果队列为空

  • 或最近一条消息还没到执行时间

👉线程进入阻塞状态

当:

  • 新消息入队

  • 或时间到达

👉线程被唤醒

因此:

next() ≠ pop()
next() = “能执行才返回,否则阻塞等待”

这是系统层设计的精髓。

十二、完整映射关系一览

C 世界Android 世界
NodeMessage
next 指针Message.next
QueueMessageQueue
for(;;)Looper.loop()
阻塞等待native poll / wake
http://www.jsqmd.com/news/98350/

相关文章:

  • PapersGPT for Zotero 终极安装指南:5步快速配置AI文献助手
  • 直播 / 录屏推流工具首选!OBS Studio v32.0.2 中文绿色版:修复崩溃 bug,免费无广告还便携
  • vlan间通信之vlanif虚接口、vlan聚合 - 教程
  • 2025年加工中心正规供应商推荐,卧式加工中心与制造商全解析 - myqiye
  • 新手快速上手动漫生成模型Counterfeit-V2.5
  • 2025抖音代运营公司TOP5权威推荐:抖音代运营套餐哪家便 - 工业品牌热点
  • 2025年设计行业聚焦:十大中国风全案公司谁主沉浮,设计4A公司推荐技术引领与行业解决方案解析 - 品牌推荐师
  • 查看Gmail 的注册地区
  • 2025年亚崴龙门靠谱生产商五大榜单,工业制造伙伴精选指南 - mypinpai
  • 快速上手Umo Editor:零配置的Vue3文档编辑器解决方案
  • 2025年上海A-Level实力培训学校推荐:看哪家口碑好? - 工业推荐榜
  • Apache Weex性能优化实战:从渲染瓶颈到极致体验的突破之路
  • 2025年靠谱的切削液集中供液/集中供液厂家推荐及选择参考 - 品牌宣传支持者
  • DeepSeek-V2.5:强大多用途语言模型详解
  • 2025年知名的单组分聚脲最新TOP品牌厂家排行 - 品牌宣传支持者
  • 2025年热门的柱塞式液压油缸/摆动式液压油缸高评价厂家推荐榜 - 品牌宣传支持者
  • 边缘AI混合模型LFM2-350M:轻量化部署的技术突破
  • 2025年抗静电型半透明HDPE再生颗粒生产厂家权威推荐榜单:半透明抗菌型HDPE再生颗粒 ‌/环钢度高聚乙烯半透明HDPE再生料‌/低挥发物半透明HDPE再生颗粒源头厂家精选 - 品牌推荐官
  • Ivy框架:打破AI开发壁垒的统一解决方案
  • “权力“和“权利“联系和区别?
  • MSBuild BuildCheck框架:构建时代码质量检查的完整指南
  • MCPServerStdio环境变量传递困境:从原理到实战的深度解决方案
  • 2025年比较好的PVC卡发卡机厂家选购指南与推荐 - 品牌宣传支持者
  • 【Rust日报】Rust 1.92.0 正式发布
  • 免费商用字体资源库:设计师必备的字体宝典
  • 2025年知名的EG屹晶微ACDC电源管理芯片/EG屹晶微PFC/LLC控制器芯片实力厂家TOP推荐榜 - 品牌宣传支持者
  • 2025 上考教育深度解析:公考培训靠谱吗?押题准度如何? - 品牌推荐排行榜
  • 8 个毕业答辩PPT工具,研究生AI降重推荐
  • 2025年12月合金光谱仪厂家权威推荐榜:精准检测与高效分析,金属成分鉴定首选利器 - 品牌企业推荐师(官方)
  • 2025年靠谱的冬令营训练基地/军事化冬令营综合实力榜 - 品牌宣传支持者