移步Android跨进程通信IPC
简介
Messenger的底层实现是AIDL,所以一些AIDL相关的内容此处不再赘述。
代码分析
1. Messenger内主要代码分析
public final class Messenger implements Parcelable {
//持有IMessenger对象,可能是IMessenger#Stub,也可能是IMessenger#Proxy
private final IMessenger mTarget;
//构造方法,根据Handler内持有的IMessenger#Stub构造
public Messenger(Handler target) {
mTarget = target.getIMessenger();
}
////构造方法,根据Binder,此时会根据不同情况产生Proxy或者Stub
public Messenger(IBinder target) {
mTarget = IMessenger.Stub.asInterface(target);
}
//发送消息
public void send(Message message) throws RemoteException {
mTarget.send(message);
}
//获取Binder对象
public IBinder getBinder() {
return mTarget.asBinder();
}
...
}
- 由上面代码可知,Messenger就是对IMessenger的一层简单封装,里面持有的IMessenger对象在服务端内是IMessenger#Stub对象。
根据AIDL内的AIDL.Stub.asInterface()的分析可知
- 如果客户端个服务端不在一个进程内,则客户端内的Messenger. IMessenger为IMessenger#Proxy对象
- 如果客户端个服务端在一个进程内,则客户端内的Messenger. IMessenger为IMessenger#Stub对象
2. Handler内Messenger的相关代码
IMessenger mMessenger;
//在Messenger的构造方法内使用
final IMessenger getIMessenger() {
synchronized (mQueue) {
if (mMessenger != null) {
return mMessenger;
}
//实例化一个IMessenger#Stub对象,并实现send()方法
mMessenger = new MessengerImpl();
return mMessenger;
}
}
获取Handler内的IMessenger #Stub对象,如不存在则创建一个
//对IMessenger.Stub的实现,并实现了send对象,通过Handler本身作为消息发送处理
private final class MessengerImpl extends IMessenger.Stub {
public void send(Message msg) {
msg.sendingUid = Binder.getCallingUid();
Handler.this.sendMessage(msg);
}
}
实现了send对象,把客户端发送过来的Message通过Handler本身作为消息发送处理,进而服务端可以接收并处理,由此可知Messenger为
串行通信
,所以不能很好的处理高并发的情形。
执行流程
Messenger和AIDL的原理是基本是完全一致的。
服务端的不同点在于实现方式和方法处理代码分析中也做了分析。
客户端的不同点仅仅是将获取IMessenger的aidl对象封装在了Messenger中。
网友评论