用最直白的大白话解释:如何创建 Message
?为什么?
1. 如何创建 Message
?
Android 中创建 Message
的常见方式有三种,核心原则是尽量复用对象,避免频繁内存分配。
(1) 直接 new Message()
val msg = Message()
msg.what = 1
msg.obj = "数据"
handler.sendMessage(msg)
- 优点:简单直接。
- 缺点:每次创建新对象,频繁调用会导致内存抖动(影响性能)。
- 不推荐:除非临时使用且消息极少。
(2) 使用 Message.obtain()
(推荐)
val msg = Message.obtain()
msg.what = 1
msg.obj = "数据"
handler.sendMessage(msg)
- 原理:从全局的消息池中复用
Message
对象。 - 优点:减少内存分配,提升性能(尤其高频消息场景)。
- 推荐场景:所有需要频繁创建消息的情况。
(3) 通过 Handler.obtainMessage()
(最简洁)
val msg = handler.obtainMessage().apply {
what = 1
obj = "数据"
}
handler.sendMessage(msg)
- 原理:内部调用
Message.obtain()
,并自动关联Handler
的Looper
。 - 优点:代码简洁,推荐使用。
2. 为什么要用 obtain()
而不是 new
?
- 消息池(Message Pool) :
Android 维护了一个全局的Message
对象池(类似“共享单车”),当消息处理完毕后,会回收到池中供复用。 - 避免内存抖动:
高频创建Message
(如列表滚动、动画)会导致频繁内存分配和回收(GC),引发卡顿。 - 性能优化:
复用对象减少内存开销,提升消息处理效率。
3. 消息池的工作机制
- 回收消息:
当Message
被处理完后,会调用recycleUnchecked()
,重置状态并放回池中。 - 复用逻辑:
Message.obtain()
优先从池中取对象,如果池为空才创建新对象。
代码示例对比
直接 new
(不推荐) :
// 每次滚动列表都 new 一个 Message(性能差)
recyclerView.addOnScrollListener(object : OnScrollListener() {
override fun onScroll() {
val msg = Message()
msg.what = SCROLL_EVENT
handler.sendMessage(msg)
}
})
使用 obtain()
(推荐) :
// 复用消息池中的对象(性能优)
recyclerView.addOnScrollListener(object : OnScrollListener() {
override fun onScroll() {
val msg = Message.obtain().apply { what = SCROLL_EVENT }
handler.sendMessage(msg)
}
})
4. 注意事项
- 不要手动修改已发送的
Message
:
消息发送后可能已被其他逻辑处理,修改会导致数据错乱。 - 及时回收:
如果是自定义的复杂Message
,处理完成后可手动调用recycle()
(但一般不需要,系统会自动处理)。 - 避免内存泄漏:
如果Message
持有Activity
或View
的引用,需在onDestroy
中移除所有消息。
总结
-
如何创建
Message
:- 推荐用
Message.obtain()
或Handler.obtainMessage()
。 - 避免直接
new Message()
。
- 推荐用
-
为什么:
- 复用对象减少内存分配,提升性能。
- 消息池机制是 Android 消息系统的核心优化手段。
口诀: “能复用,别新建;高频消息用池管” !