Messenger
1、Messenger
Messenger在不同进程中传递Message对象,在Message中放入我们需要传递的信息,然后通过Messenger将Message传递给对方,就可以轻轻松松实现跨进程数据传递。Messenger是轻量级的IPC(跨进程通信)方式,底层是AIDL实现。
“Reference to a Handler, which others can use to send messages to it. This allows for the implementation of message-based communication across processes, by creating a Messenger pointing to a Handler in one process, and handing that Messenger to another process.”

2、服务端
先来看服务端Messenger的编码工作。
2.1、Handler
继承Handler自定义Handler,处理Messenger中的Message消息:
private static class MessengerHandler extends Handler {
public void handleMessage(Message msg) {
switch (msg.what) {
...
default:
break;
}
}
}2.2、创建Messenger
将前面定义的Handler作为Messenger构造函数的参数,创建Messenger
private final Messenger mMessenger = new Messenger(new MessengerHandler());2.3、onBind()
服务端Service的onBinder()中返回Messenger获得的IBinder:
@Override
public IBinder onBind(Intent intent) {
return mMessenger.getBinder();
}3、客户端
客户端绑定另一个APP或者进程的Service,通过Messenger通信。
3.1、Messenger
客户端定义一个Messenger对象,在绑定到服务端的时候初始化,“引用”到服务端对应的Messenger
private Messenger mMessenger;3.2、ServiceConnection
服务端Service需要和客户端绑定的方式启动,先定义ServiceConnection:
private ServiceConnection mServiceConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName name, IBinder service) {
//这里服务端连接上,初始化客户端Messenger
mMessenger = new Messenger(service);
}
public void onServiceDisconnected(ComponentName name) {
}
};3.3、绑定服务
通过下面的方式绑定服务端Service,包名是一定要有的。还可以给Intent设置Service一致的Action启动。
Intent intent = new Intent();
ComponentName componentName = new ComponentName("服务端包名", "服务端Service完整路径");
intent.setComponent(componentName);
bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);3.4、给Service发送Message消息
绑定成功Service,也获取到Messenger对象,就可以借助Messenger向服务端发送消息。需要try-catch,因为可能会抛出RemoteException受查异常。
Message message = Message.obtain(null, 1);
try {
mMessenger.send(message);
} catch (RemoteException e) {
}4、服务端->客户端
前面的是客户端给服务端发送Messenger消息,服务端能不能回应客户端的消息,向客户端发送消息呢?可以。就像是反过来,客户端成了服务端,服务端成了客户端。
4.1、客户端
首先,客户端增加处理服务端发送Message的Messenger和Handler。
客户端定义Handler ,处理服务端的Message:
private static class MessengerHandler extends Handler {
public void handleMessage( Message msg) {
switch (msg.what) {
...
}
}
}再在客户端定义一个Messenger
private Messenger mClientMessenger = new Messenger(new MessengerHandler());向服务端发送Message的时候,借助Message中的replyTo字段携带上该客户端Messenger:
Message message = Message.obtain(null, 1);
message.replyTo = mClientMessenger;
try {
mMessenger.send(message);
} catch (RemoteException e) {
}4.2、服务端
接下来就是服务端收到客户端的Message,再给客户端发送Message消息,修改服务端中自定义的Handler,从客户端发送的Message中拿到客户端的Messenger,向客户端发送消息:
private static class MessengerHandler extends Handler {
public void handleMessage(Message msg) {
switch (msg.what) {
case CLIENT:
//拿到客户端的Messenger
Messenger clientMessenger = msg.replyTo;
Message replyMessage = Message.obtain(null, 1);
try {
//向客户端发送消息
clientMessenger.send(replyMessage);
} catch (RemoteException e) {
Log.e("QUIBBLER", "服务端->客户端失败");
}
}
}
}5、Messenger与AIDL
Messenger底层就是AIDL实现的,是系统封装提供的一个实用进程间通信工具。在《Android开发艺术探索》一书中有详细提到。这里直接引用简书 利用Messenger跨进程通信一文。
5.1、相同点
①都与IPC的调用有关;
②Messenger 是一种轻量级的 IPC方案,底层实现了AIDL,只是进行了封装,开发的时候不用写.aidl文件。
③都支持实时通信;
5.2、不同点
①Messenger一次只能处理一个请求(串行);AIDL一次可以处理多个请求(并行);
当需要执行 IPC 时,为您的接口使用 Messenger 要比使用 AIDL 实现更加简单,因为 Messenger 会将所有服务调用排入队列,而纯粹的 AIDL 接口会同时向服务发送多个请求,服务随后必须应对多线程处理。
对于大多数应用,服务不需要执行多线程处理,因此使用 Messenger 可让服务一次处理一个调用。如果您的服务必须执行多线程处理,则应使用 AIDL 来定义接口。
②Messenger不支持RPC,只能通过Message传递消息;AIDL支持RPC;
③Messenger使用简单,轻量级,不需要创建AIDL文件;AIDL使用复杂,需要创建AIDL文件;
相关资料:
Android Developers>Docs>Reference

