深入解析AndroidIPC中的Messenger机制
作者:手机用户2502918445 | 来源:互联网 | 2024-12-21 11:11
本文详细介绍了Android中基于消息传递的进程间通信(IPC)机制——Messenger。通过实例和源码分析,帮助开发者更好地理解和使用这一高效的通信工具。
在之前的文章中,我们探讨了使用 AIDL 实现 Android IPC 的方法。今天我们将聚焦于另一种常用的 IPC 方式——Messenger。 ### 一、Messenger 概述 Messenger 是一种基于消息传递的进程间通信机制。它允许不同进程之间的对象通过 Handler 发送和接收消息。具体来说,一个进程可以通过创建指向本地 Handler 的 Messenger 对象,并将其传递给另一个进程来实现跨进程通信。 #### 工作原理 1. **服务端与客户端**:Messenger 需要服务端和客户端两部分。客户端需要绑定到远程服务,成功后可以获取远程 IBinder 对象并由此得到远程的 Messenger 对象。 2. **消息发送**:客户端向服务端发送消息时,需使用从服务端获取的 Messenger 对象,并将自身的 Messenger 对象作为回复地址附加在消息中。 3. **消息回复**:服务端接收到消息后,可以通过消息中的 replyTo 属性找到客户端的 Messenger 对象,从而向客户端发送响应。  ### 二、实例演示 为了展示 Messenger 的实际应用,我们可以创建两个独立的应用程序,分别作为服务端和客户端。这里以服务端为例,展示如何处理来自客户端的消息并返回响应。 ```java public class MessengerService extends Service { private static final String TAG = "MessengerService"; private static final int WHAT = 0x101; private final Handler mHandler = new Handler(Looper.getMainLooper()) { @Override public void handleMessage(Message msg) { switch (msg.what) { case WHAT: Bundle bundle = (Bundle) msg.obj; String str = bundle.getString("str"); Log.e(TAG, "收到客户端消息: " + str); // 回复客户端 Message reply = Message.obtain(); Bundle replyBundle = new Bundle(); replyBundle.putString("str", "已收到,继续努力!"); reply.setData(replyBundle); try { msg.replyTo.send(reply); } catch (RemoteException e) { e.printStackTrace(); } break; } } }; private final Messenger mMessenger = new Messenger(mHandler); @Nullable @Override public IBinder onBind(Intent intent) { return mMessenger.getBinder(); } } ``` 客户端代码负责绑定服务并发送初始消息。当接收到服务端的响应时,会显示在日志中。 ```java public class MainActivity extends AppCompatActivity { private static final String TAG = "MainActivity"; private static final int WHAT = 0x102; private boolean isBound; private Messenger mClientMessenger = new Messenger(new Handler(Looper.getMainLooper()) { @Override public void handleMessage(Message msg) { if (msg.what == WHAT) { Bundle bundle = msg.getData(); String respOnse= bundle.getString("str"); Log.e(TAG, "收到服务端回复: " + response); } } }); private Messenger mServiceMessenger; private ServiceConnection mCOnnection= new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { mServiceMessenger = new Messenger(service); isBound = true; sendInitialMessage(); } @Override public void onServiceDisconnected(ComponentName name) { mServiceMessenger = null; isBound = false; } }; private void sendInitialMessage() { Message message = Message.obtain(null, WHAT); Bundle bundle = new Bundle(); bundle.putString("str", "你好,我是客户端"); message.setData(bundle); message.replyTo = mClientMessenger; try { mServiceMessenger.send(message); } catch (RemoteException e) { e.printStackTrace(); } } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); findViewById(R.id.btn_start_service).setOnClickListener(v -> bindService()); } private void bindService() { Intent intent = new Intent("cn.xinxing.messengerservice"); bindService(intent, mConnection, Context.BIND_AUTO_CREATE); } @Override protected void onDestroy() { super.onDestroy(); if (isBound) { unbindService(mConnection); } } } ``` ### 三、源码剖析 Messenger 的核心在于其构造函数和内部使用的 IMessenger 接口。构造函数接受一个 Handler 并从中提取出 IMessenger 对象。IMessenger 是一个 AIDL 接口,定义了 send 方法用于跨进程传递消息。 ```java public Messenger(Handler target) { mTarget = target.getIMessenger(); } ``` `getIMessenger()` 方法返回一个实现了 IMessenger 接口的对象,即 `MessengerImpl`。这个类重写了 send 方法,利用 Handler 来分发消息。 ```java private final class MessengerImpl extends IMessenger.Stub { public void send(Message msg) { msg.sendingUid = Binder.getCallingUid(); Handler.this.sendMessage(msg); } } ``` ### 四、总结 - **底层实现**:Messenger 基于 AIDL 构建,但封装了复杂的细节,简化了开发者的使用。 - **通信方式**:服务端和客户端之间通过各自持有的 Messenger 对象进行消息交换。 - **参数传递**:所有数据必须实现 Parcelable 接口,推荐使用 Bundle 封装参数。 - **线程支持**:Messenger 默认是单线程的,不支持并发操作。若需多线程,请考虑使用 AIDL 或其他方案。 希望本文能帮助你更深入地理解 Android IPC 中的 Messenger 机制及其应用场景。
推荐阅读
本文详细介绍了Java中org.neo4j.helpers.collection.Iterators.single()方法的功能、使用场景及代码示例,帮助开发者更好地理解和应用该方法。 ...
[详细]
蜡笔小新 2024-12-28 10:51:55
Explore a common issue encountered when implementing an OAuth 1.0a API, specifically the inability to encode null objects and how to resolve it. ...
[详细]
蜡笔小新 2024-12-28 08:54:34
本文详细介绍了Java中org.eclipse.ui.forms.widgets.ExpandableComposite类的addExpansionListener()方法,并提供了多个实际代码示例,帮助开发者更好地理解和使用该方法。这些示例来源于多个知名开源项目,具有很高的参考价值。 ...
[详细]
蜡笔小新 2024-12-27 16:11:49
本文介绍了一段通用代码示例,该代码不仅能够操作 Azure Active Directory (AAD),还可以通过 Azure Service Principal 的授权访问和管理 Azure 订阅资源。Azure 的架构可以分为两个层级:AAD 和 Subscription。 ...
[详细]
蜡笔小新 2024-12-27 16:07:12
在前两篇文章中,我们探讨了 ControllerDescriptor 和 ActionDescriptor 这两个描述对象,分别对应控制器和操作方法。本文将基于 MVC3 源码进一步分析 ParameterDescriptor,即用于描述 Action 方法参数的对象,并详细介绍其工作原理。 ...
[详细]
蜡笔小新 2024-12-27 15:26:10
本文详细解析了 DotNetNuke (DNN) 的两种主要版本:Community 和 Professional。通过对比两者的功能和附加组件,帮助用户选择最适合其需求的版本。 ...
[详细]
蜡笔小新 2024-12-27 13:14:08
本文深入探讨了如何通过多种技术手段优化ListView的性能,包括视图复用、ViewHolder模式、分批加载数据、图片优化及内存管理等。这些方法能够显著提升应用的响应速度和用户体验。 ...
[详细]
蜡笔小新 2024-12-28 10:36:30
本文探讨了在Windows 10(64位)环境下开发的Windows服务,旨在定期向本地MS SQL Server (v.11)插入记录。尽管服务已成功安装并运行,但记录并未正确插入。我们将详细分析可能的原因及解决方案。 ...
[详细]
蜡笔小新 2024-12-28 10:30:14
本文将介绍如何编写一些有趣的VBScript脚本,这些脚本可以在朋友之间进行无害的恶作剧。通过简单的代码示例,帮助您了解VBScript的基本语法和功能。 ...
[详细]
蜡笔小新 2024-12-28 09:46:23
本文详细介绍了Spring Cloud中的Ribbon组件如何实现服务调用的负载均衡。通过分析其工作原理、源码结构及配置方式,帮助读者理解Ribbon在分布式系统中的重要作用。 ...
[详细]
蜡笔小新 2024-12-27 16:01:25
本文详细介绍了Akka中的BackoffSupervisor机制,探讨其在处理持久化失败和Actor重启时的应用。通过具体示例,展示了如何配置和使用BackoffSupervisor以实现更细粒度的异常处理。 ...
[详细]
蜡笔小新 2024-12-27 15:04:09
本文介绍了如何在 Android 中创建一个自定义的渐变圆环加载控件,该控件已在多个知名应用中使用。我们将详细探讨其工作原理和实现方法。 ...
[详细]
蜡笔小新 2024-12-27 13:34:19
Explore how Matterverse is redefining the metaverse experience, creating immersive and meaningful virtual environments that foster genuine connections and economic opportunities. ...
[详细]
蜡笔小新 2024-12-28 09:44:49
本文详细介绍了如何在Linux系统上安装和配置Smokeping,以实现对网络链路质量的实时监控。通过详细的步骤和必要的依赖包安装,确保用户能够顺利完成部署并优化其网络性能监控。 ...
[详细]
蜡笔小新 2024-12-27 19:31:05
本文介绍了一款用于自动化部署 Linux 服务的 Bash 脚本。该脚本不仅涵盖了基本的文件复制和目录创建,还处理了系统服务的配置和启动,确保在多种 Linux 发行版上都能顺利运行。 ...
[详细]
蜡笔小新 2024-12-27 16:33:32
手机用户2502918445
这个家伙很懒,什么也没留下!