Android Messenger 笔记

replyToMessenger 的跨进程通信(IPC, Inter-Process Communication)中,扮演着至关重要的角色------它是建立起客户端与服务端之间双向通信通道的桥梁

你可以把它想象成一个"回信地址 "。当客户端向服务端发送消息时,通过在消息中附带上自己的 replyTo 信使,就相当于告诉服务端:"如果你需要回复我,请寄到这个地址。"

下面,我们来详细拆解这个过程。

🧭 replyTo 的核心作用与双向通信流程

Messenger 本身是一种轻量级的 IPC 方案,其底层实现是对 AIDL 的封装,因此使用起来非常简单 。但它的设计是"单工"的,即默认只支持单向通信。要实现双向对话,就必须依赖 replyTo

整个流程可以用以下几个步骤清晰地概括 :

sequenceDiagram participant Client participant Server Note over Client: 1. 创建自己的Handler<br/>和Messenger (clientMessenger) Client->>Server: 2. 绑定服务,获得服务端Messenger Client->>Server: 3. 创建Message,设置数据<br/>并执行 msg.replyTo = clientMessenger Server->>Server: 4. 服务端Handler处理消息 Server->>Client: 5. 从msg.replyTo中取出clientMessenger<br/>用它向客户端发送回复消息 Client->>Client: 6. 客户端Handler处理服务端的回复

💻 代码实现详解

下面通过一个简单的示例,来看看代码中是如何体现的。

📱 客户端(Client)

客户端需要做两件事:一是发送消息,二是准备好接收回复的"信箱"。

java 复制代码
// 1. 创建自己的"信箱",用于接收服务端的回复
private static class ReplyHandler extends Handler {
    @Override
    public void handleMessage(Message msg) {
        switch (msg.what) {
            case MSG_REPLY_FROM_SERVICE:
                // 收到服务端的回复,进行UI更新等操作
                String replyText = msg.getData().getString("reply");
                Log.i("Client", "收到服务端回复: " + replyText);
                break;
        }
    }
}
// 客户端的信使,专门负责接收回复
private Messenger mReplyMessenger = new Messenger(new ReplyHandler());

// 2. 与服务端建立连接后,发送消息
private ServiceConnection mConnection = new ServiceConnection() {
    public void onServiceConnected(ComponentName className, IBinder service) {
        // 拿到服务端的信使
        Messenger mServiceMessenger = new Messenger(service);
        // 创建要发送的消息
        Message msg = Message.obtain(null, MSG_FROM_CLIENT, 0, 0);
        Bundle data = new Bundle();
        data.putString("request", "你好,服务端!");
        msg.setData(data);
        
        // ***** 关键步骤:设置 replyTo,附上自己的"回信地址" *****
        msg.replyTo = mReplyMessenger;
        
        try {
            mServiceMessenger.send(msg);
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }
    public void onServiceDisconnected(ComponentName className) { }
};

💻 服务端(Server)

服务端的任务则是接收消息、解析 replyTo,并使用它来回复。

java 复制代码
public class MessengerService extends Service {
    private static class ServiceHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_FROM_CLIENT:
                    // 1. 处理客户端发来的请求
                    String request = msg.getData().getString("request");
                    Log.i("Server", "收到客户端请求: " + request);
                    
                    // 2. ***** 关键步骤:通过 msg.replyTo 拿到客户端的信使 *****
                    Messenger clientMessenger = msg.replyTo;
                    
                    // 3. 创建回复消息
                    Message replyMsg = Message.obtain(null, MSG_REPLY_FROM_SERVICE);
                    Bundle replyData = new Bundle();
                    replyData.putString("reply", "你的消息已收到,谢谢!");
                    replyMsg.setData(replyData);
                    
                    // 4. 使用客户端的信使将消息发回
                    try {
                        clientMessenger.send(replyMsg);
                    } catch (RemoteException e) {
                        e.printStackTrace();
                    }
                    break;
            }
        }
    }
    
    private final Messenger mServerMessenger = new Messenger(new ServiceHandler());
    
    @Override
    public IBinder onBind(Intent intent) {
        // 返回底层的Binder,供客户端构造自己的Messenger
        return mServerMessenger.getBinder(); 
    }
}

关键点总结

  1. 服务端 :通过 msg.replyTo 获取客户端信使,并使用它发送回复 。
  2. 客户端 :创建自己的 Messenger 并赋值给 msg.replyTo,以此将自己的"回信地址"传递给服务端 。

💡 进阶要点与注意事项

了解基本用法后,以下几个要点能帮你更深入地理解和使用 Messenger

  • 串行处理Messenger 在服务端是通过 Handler 来处理消息的。这意味着所有来自客户端的请求会被串行地 在服务端的 Handler 所在线程中执行,不存在并发问题,因此你无需考虑线程同步,这是它相较于直接使用 AIDL 的一个主要优势 。
  • 与 AIDL 的对比 :如果说 AIDL 是让你能够直接调用远程进程的方法,那 Messenger 就是一种基于消息的、更简单的 IPC 方式。你可以把 Messenger 理解为系统对 AIDL 的一次封装,它更适合于消息驱动的跨进程通信场景 。
  • 数据传递限制 :通过 Messenger 发送的 Message 对象,其传递的数据大小受 Binder 事务缓冲区限制,通常为 1MB 。这是所有 Binder 通信的共同限制,需要注意避免传递过大的数据,否则会引发 TransactionTooLargeException 异常 。

希望这份讲解能帮助你完全掌握 replyToMessenger 跨进程通信中的妙用。如果对其中某个环节还有疑问,比如它的底层实现或与其他IPC方式的对比,我们可以继续探讨。

相关推荐
Godikov5 小时前
硬件异步事件下的业务一致性:智能柜领取/归还流程的竞态设计
android
Godikov5 小时前
不用 Netty:Android 手写 TCP 客户端实战——自定义协议帧、粘包处理与可靠重连
android
事圆则缓5 小时前
Java 面向对象如何落到 Android View 体系
android
iPad协议个微协议6 小时前
# 微信自动营销系统如何基于 WechatApi 做事件驱动设计
android·微信·企业微信·个人开发·wechatapi·微信个人号开发
AirDroid_cn6 小时前
隐私沙盒:第三方应用读取剪切板内容如何拦截?
android·gitee
2501_915918418 小时前
怎么把 Python 写的 Flet 应用打包成 iOS App 并上架 App Store?
android·ios·小程序·https·uni-app·iphone·webview
邪修king9 小时前
Re:Linux系统篇(二十六):文件系统(二):Ext 文件系统底层详解:从 inode、块组到软硬链接,结合 Windows 讲透文件管理本质
android·java·linux
又见情义10 小时前
RK3568 Android 13 版本号管理实战:基于 ROCKCHIP_BUILD_NUMBER 的定制化方案
android
终端安全笔记10 小时前
iOS 27 强制 TLS 1.2:租赁设备的注册链路会在哪一环断
android·网络·安全·ios·智能手机
mmsx10 小时前
MapLibre 实战 11|用户说"我的地块丢了":一个 sealed class 图层模型,和四个让我重构三版的坑
android·前端·开源