概念
让服务与远程进程通信,可使用 Messenger
为服务提供接口。通过 Messenger
发送消息(Message
)来实现进程间的通信 (IPC
)。
Messenger
实现双向通信及示例
通信流程
- 双方实例化
Messenger
Activity
和Service
两边各自都要实例化Messenger
,分别为:AMessenger
和SMessenger
。 Activity
到Service
的通信Service
在onBind
时,返回SMessenger
的IBinder
。Activity
在bindService
连接后,通过该IBinder
得到SMessenger
实例,并通过它来向Service
发送消息。Service
到Activity
的通信(回调)Activity
组建消息Message
并将AMessenger
存放消息中,再通过SMessenger
实例发送消息时传递给Service
,Service
通过拿到的AMessenger
实例发送消息,形成对Activity
的回调。
服务端
- 定义各种
Message
的ID
1 | // 从客户端来的消息 |
- 自定义
Handler
并实例化SMessenger
接受来自客户端的消息,后台处理:
1 | /** Keeps track of all current registered clients. */ |
onBind
返回Messenger
1 |
|
- 服务端向客户端发送消息(回调)
1 | private void feedbackToClient(Messenger replyTo){ |
客户端
- 自定义
Handler
并实例化AMessenger
接受来自服务端的消息,响应回调:
1 | private class IncomingFromServiceHandler extends Handler { |
- 绑定服务后获取
SMessenger
其中mService
即从服务器端获取到的SMessenger
:
1 | /** Flag indicating whether we have called bind on the service. */ |
- 客户端向服务端发送消息
也就是客户端有两个Messenger
的实例,一个用于响应回调的AMessenger
,一个用于发送消息的SMessenger
:
1 | private void doLongRunningWork(){ |
示例及 Log
分析
客户端向服务端下发耗时任务,并响应服务端的回调
1 | // 启动客户端 Activity |
客户端同时下发三条耗时任务
下发了三条耗时任务,服务端串行接收这些消息并处理。耗时任务是新建线程执行的,可以等待该线程执行完了再接受消息(即串行执行耗时任务),也可以接受消息时再开启新开线程执行(即并行执行耗时任务),示例是并行执行耗时任务:
1 | // 绑定服务 |
自定义 Parcelable
数据传输
进程间通信时,Messenger
在传递数据时,需要通过 Bundle
将自定义的数据打包传输。但是另一个进程在取出 Bundle
时的 ClassLoader
为 null
,会使用系统默认值 BootClassLoader
来加载自定义的 Parcelable
数据,所以会出现异常找不到该数据类。如果是在相同进程中使用 Messenger
则不会出现这个问题,不过如果是相同进程也不需要使用 Messenger
来通信了。
- 解决方案
在取出Parcelable
数据前,设置该应用为ClassLoader
的值:
1 | if(msg != null && msg.getData() != null){ |
- 异常
ClassNotFoundException
异常Log
:
1 | 14:50:33.803 14568-14568/:messenger D/AndroidRuntime: Shutting down VM |
源码分析
从源码可以看出:Messenger
的本质还是使用的 AIDL
,只是封装后更方便使用。
1 | // Messenger.java |
Messenger
和 Message
的区别和联系
从源码中可以看出,Message
是一个包含各种数据的容器,Messenger
可以作为 Parcelable
数据,通过 Message
装载后传递出去。而从 Messenger
的 AIDL
来看,它唯一的方法就是发送 Message
,是一名信差。
Messenger
总结
- 本质还是
AIDL
- 只能异步通信,同步的话必须使用
AIDL
- 因为使用的是
Handler
和Message
,所以所有的消息都是串行接受和处理的,处理的过程可以是多线程或单线程来处理