Android随笔-Handler的Message是什么结构 Message 是对象它就是 Java 中的一个普通类继承自 Object。但 Android 对它做了大量优化让它在 Handler 机制中高效复用避免频繁创建和 GC。一、Message 的本质publicfinalclassMessageimplementsParcelable{publicintwhat;// 消息标识publicintarg1,arg2;// 轻量整型参数publicObjectobj;// 任意对象参数publicMessengerreplyTo;// 跨进程回复publiclongwhen;// 消息触发时间Bundledata;// 数据载体Handlertarget;// 目标 HandlerRunnablecallback;// 回调 Runnable// 链表指针用于消息池Messagenext;// 单链表指向池中的下一个 Message// 同步锁对象privatestaticfinalObjectsPoolSyncnewObject();// 消息池头节点privatestaticMessagesPool;// 消息池当前大小privatestaticintsPoolSize0;// 消息池最大容量privatestaticfinalintMAX_POOL_SIZE50;}核心点Message 是普通 Java 类不是基本类型不是 native 结构但它内部维护了一个静态消息池sPool用单链表实现对象复用二、消息池机制为什么高效1. 获取 Messageobtain()publicstaticMessageobtain(){synchronized(sPoolSync){if(sPool!null){MessagemsPool;// 从池头取一个sPoolm.next;// 池头后移m.nextnull;// 断开链表m.flags0;// 重置状态sPoolSize--;// 池大小减1returnm;// 返回复用的对象}}returnnewMessage();// 池空了才 new}2. 回收 Messagerecycle()publicvoidrecycle(){if(isInUse()){// 正在使用的消息不能回收return;}recycleUnchecked();}voidrecycleUnchecked(){// 重置所有字段flagsFLAG_IN_USE;what0;arg10;arg20;objnull;replyTonull;sendingUid-1;workSourceUid-1;when0;targetnull;callbacknull;datanull;synchronized(sPoolSync){if(sPoolSizeMAX_POOL_SIZE){nextsPool;// 头插法把自己插到池头sPoolthis;// 更新池头sPoolSize;// 池大小加1}}}3. 池结构示意初始状态sPool null, sPoolSize 0 obtain() 第1次池空 → new Message() → 返回新对象 obtain() 第2次池空 → new Message() → 返回新对象 // 两个消息被处理完后 recycle() recycle(msg2): msg2.next null; sPool msg2; sPoolSize 1 recycle(msg1): msg1.next msg2; sPool msg1; sPoolSize 2 // 再次 obtain() obtain(): 取 sPool(msg1); sPool msg2; sPoolSize 1 → 复用 msg1 obtain(): 取 sPool(msg2); sPool null; sPoolSize 0 → 复用 msg2三、为什么不用 new Message()方式结果new Message()堆上分配内存增加 GC 压力Message.obtain()优先从池复用几乎零分配实际效果一个高频 Handler如刷新 UI、动画每秒发 60 条消息用 obtain()前几次 new 之后全部从池复用零 GC用 new Message()每秒 60 个临时对象频繁 Young GC四、MessageQueue 中的 Message 是怎么存的publicfinalclassMessageQueue{MessagemMessages;// 消息队列头按 when触发时间排序的单链表// 入队booleanenqueueMessage(Messagemsg,longwhen){synchronized(this){msg.whenwhen;MessagepmMessages;if(pnull||when0||whenp.when){msg.nextp;// 插到队头mMessagesmsg;}else{// 按时间顺序找到插入位置Messageprev;for(;;){prevp;pp.next;if(pnull||whenp.when){break;}}msg.nextp;// 插入中间prev.nextmsg;}}returntrue;}}关键MessageQueue 本身也是用Message 的单链表实现不是数组不是队列类。Message.next 同时服务于两个链表消息池链表复用消息队列链表按时间排序五、与 Handler、Looper 的关系Looper.prepare() → 创建 Looper MessageQueue ↓ Looper.loop() → 无限循环 ├── MessageQueue.next() → 取消息阻塞/等待 │ └── 没到时间 → nativePollOnce() 休眠 │ └── 到时间了 → 返回 Message ├── msg.target.dispatchMessage(msg) → Handler 处理 │ └── msg.recycleUnchecked() → 回收到消息池 └── 继续循环六、常见误区误区真相“Message 是基本类型”❌ 是对象但用池复用“MessageQueue 用数组”❌ 用 Message 单链表“new Message() 和 obtain() 一样”❌ obtain() 优先复用性能差很多“消息池无限大”❌ 最大 50 个满了直接丢弃不回收“recycle() 后消息还能用”❌ 回收后字段全清空再用是未定义行为七、最佳实践// ✅ 正确用 obtain复用消息池MessagemsgMessage.obtain(handler,what,arg1,arg2,obj);handler.sendMessage(msg);// ✅ 正确用便捷方法内部也是 obtainhandler.obtainMessage(what).sendToTarget();handler.sendEmptyMessage(what);// ❌ 错误直接 new浪费内存MessagemsgnewMessage();// 不要这样八、总结Message 是 Java 对象不是基本类型也不是 native 结构。Android 用静态单链表维护了一个最大容量 50 的消息池通过 obtain() 复用、recycle() 回收避免高频 Handler 场景下的对象创建和 GC。MessageQueue 本身也是用 Message.next 指针串成的按时间排序的单链表——整个 Handler 机制的核心数据结构就是这一条 Message 链表在消息池和消息队列之间来回流转。

相关新闻

最新新闻

SerenityOS 命令行选项解析指南:getopt 与 getopt_long 用法、返回值与底层实现

SerenityOS 命令行选项解析指南:getopt 与 getopt_long 用法、返回值与底层实现

SerenityOS 命令行选项解析指南:getopt 与 getopt_long 用法、返回值与底层实现 【免费下载链接】serenity The Serenity Operating System 🐞 项目地址: https://gitcode.com/GitHub_Trending/se/serenity 导读 本文以 getopt(3) 手册 为核心&a…

2026/9/30 14:41:37
轻量服务器还是ECS?大促云服务器选购与避坑实战指南

轻量服务器还是ECS?大促云服务器选购与避坑实战指南

每年大促节点,群里永远有人在问同一个问题:“38元的轻量服务器到底怎么抢?为什么我每次点进去都是已售罄?68元直购和99元的ECS我到底选哪个?”作为一个常年帮团队和自己采购云服务器的老用户,我太清楚这种纠…

2026/9/30 21:32:07
为 AI 代理的 Review 动作编写 Cedar 审批门控策略:review-agent-governance 策略编写实战指南

为 AI 代理的 Review 动作编写 Cedar 审批门控策略:review-agent-governance 策略编写实战指南

为 AI 代理的 Review 动作编写 Cedar 审批门控策略:review-agent-governance 策略编写实战指南 【免费下载链接】agents Multi-harness agentic plugin marketplace for Claude Code, Codex, Cursor, OpenCode, GitHub Copilot, and Google Antigravity 项目地址:…

2026/9/30 19:41:56
PaddleOCR 手写数学公式识别算法 CAN 实战指南:Counting-Aware Network 训练、评估与推理部署

PaddleOCR 手写数学公式识别算法 CAN 实战指南:Counting-Aware Network 训练、评估与推理部署

PaddleOCR 手写数学公式识别算法 CAN 实战指南:Counting-Aware Network 训练、评估与推理部署 【免费下载链接】PaddleOCR Turn any PDF or image document into structured data for your AI. A powerful, lightweight OCR toolkit that bridges the gap between i…

2026/9/30 18:23:43
Spring源码解析:构造器注入的类型转换与候选匹配机制

Spring源码解析:构造器注入的类型转换与候选匹配机制

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/29 22:57:57
openai-agents-python 多模型接入指南:深入解析 AnyLLMModel 适配层与 any-llm 路由

openai-agents-python 多模型接入指南:深入解析 AnyLLMModel 适配层与 any-llm 路由

openai-agents-python 多模型接入指南:深入解析 AnyLLMModel 适配层与 any-llm 路由 【免费下载链接】openai-agents-python A lightweight, powerful framework for multi-agent workflows 项目地址: https://gitcode.com/GitHub_Trending/op/openai-agents-pyth…

2026/9/30 21:32:11

日新闻

周新闻

月新闻