一句话说透Android里面的如何创建Message?为什么?

130 阅读2分钟

用最直白的大白话解释:如何创建 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. 注意事项

  1. 不要手动修改已发送的 Message
    消息发送后可能已被其他逻辑处理,修改会导致数据错乱。
  2. 及时回收
    如果是自定义的复杂 Message,处理完成后可手动调用 recycle()(但一般不需要,系统会自动处理)。
  3. 避免内存泄漏
    如果 Message 持有 Activity 或 View 的引用,需在 onDestroy 中移除所有消息。

总结

  • 如何创建 Message

    • 推荐用 Message.obtain() 或 Handler.obtainMessage()
    • 避免直接 new Message()
  • 为什么

    • 复用对象减少内存分配,提升性能
    • 消息池机制是 Android 消息系统的核心优化手段。

口诀“能复用,别新建;高频消息用池管”