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 链表在消息池和消息队列之间来回流转。