跳到主要内容

Messenger

问题

Messenger 是什么?和 AIDL 有什么区别?

答案

Messenger 原理

Messenger 是 AIDL 的轻量封装,底层仍然基于 Binder,但所有消息在 Server 端的 Handler 中串行处理,不需要考虑线程同步:

Server 端

class MessengerService : Service() {

private val handler = object : Handler(Looper.getMainLooper()) {
override fun handleMessage(msg: Message) {
when (msg.what) {
MSG_SAY_HELLO -> {
val name = msg.data.getString("name")
Log.d("Server", "Hello from $name")

// 回复 Client
msg.replyTo?.send(Message.obtain(null, MSG_REPLY).apply {
data = Bundle().apply { putString("result", "Welcome, $name!") }
})
}
}
}
}

private val messenger = Messenger(handler)

override fun onBind(intent: Intent): IBinder = messenger.binder

companion object {
const val MSG_SAY_HELLO = 1
const val MSG_REPLY = 2
}
}

Client 端

class MessengerActivity : AppCompatActivity() {
private var serverMessenger: Messenger? = null

// Client 也创建 Messenger 接收回复
private val clientHandler = object : Handler(Looper.getMainLooper()) {
override fun handleMessage(msg: Message) {
when (msg.what) {
MessengerService.MSG_REPLY -> {
val result = msg.data.getString("result")
Log.d("Client", "Reply: $result")
}
}
}
}
private val clientMessenger = Messenger(clientHandler)

private val connection = object : ServiceConnection {
override fun onServiceConnected(name: ComponentName, service: IBinder) {
serverMessenger = Messenger(service)
sendMessage()
}
override fun onServiceDisconnected(name: ComponentName) {
serverMessenger = null
}
}

private fun sendMessage() {
val msg = Message.obtain(null, MessengerService.MSG_SAY_HELLO).apply {
data = Bundle().apply { putString("name", "Client") }
replyTo = clientMessenger // 设置回复的 Messenger
}
serverMessenger?.send(msg)
}
}

Messenger vs AIDL

特性MessengerAIDL
复杂度简单较复杂
线程模型串行(Handler)并发(Binder 线程池)
数据类型Message + Bundle自定义接口
适用场景简单消息传递复杂接口、高频调用
同步调用❌ 只能异步✅ 支持
选型建议
  • 简单消息传递(如通知、状态同步)→ Messenger
  • 复杂接口方法(如获取数据列表、回调)→ AIDL

常见面试问题

Q1: Messenger 为什么是线程安全的?

答案

Messenger 底层使用 IMessenger.aidl(系统内置),所有消息最终通过 Handler.sendMessage() 投递到 Handler 绑定的 Looper 的 MessageQueue 中。Looper 是单线程循环处理消息,因此所有请求天然串行执行,不存在并发竞争问题。

相关链接