一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第7天,点击查看活动详情。
Messenger内部同时提供了服务端和客户端对应的方法,getBinder()是通过mTarget来返回的,mTarget是通过Handler的getIMessenger()来返回的,具体实现是在Handler内部,一起看一下Handler的内部对应的实现:
b.Handler.java
final IMessenger getIMessenger() {
synchronized (mQueue) {
if (mMessenger != null) {
return mMessenger;
}
mMessenger = new MessengerImpl();
return mMessenger;
}
}
private final class MessengerImpl extends IMessenger.Stub {
public void send(Message msg) {
msg.sendingUid = Binder.getCallingUid();
Handler.this.sendMessage(msg);
}
}
c.IMessenger.aidl
oneway interface IMessenger {
void send(in Message msg);
}
d.IMessenger.java
public interface IMessenger extends android.os.IInterface {
/** Local-side IPC implementation stub class. */
public static abstract class Stub extends android.os.Binder implements android.os.IMessenger {
private static final java.lang.String DESCRIPTOR = "android.os.IMessenger";
/** Construct the stub at attach it to the interface. */
public Stub() {
this.attachInterface(this, DESCRIPTOR);
}
........
........
@Override public android.os.IBinder asBinder() {
return this;
}
@Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException {
switch (code)
..........
case TRANSACTION_send: {
data.enforceInterface(DESCRIPTOR);
android.os.Message _arg0;
if ((0!=data.readInt())) {
_arg0 = android.os.Message.CREATOR.createFromParcel(data);
} else {
_arg0 = null;
}
this.send(_arg0);
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
private static class Proxy implements android.os.IMessenger {
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote) {
mRemote = remote;
}
@Override public android.os.IBinder asBinder() {
return mRemote;
}
.........
@Override public void send(android.os.Message msg) throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
if ((msg!=null)) {
_data.writeInt(1);
msg.writeToParcel(_data, 0);
} else {
_data.writeInt(0);
}
mRemote.transact(Stub.TRANSACTION_send, _data, null, android.os.IBinder.FLAG_ONEWAY);
} finally {
_data.recycle();
}
}
}
static final int TRANSACTION_send = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
}
public void send(android.os.Message msg) throws android.os.RemoteException;
}
从上面可以看到,getIMessenger()返回的是MessengerImpl实例,而MessengerImpl是继承了IMessenger.Stub,实现了send()方法来接收消息,从这里可以看到,用的是跟AIDL相同的处理;
总结一下
服务端:service的onBind()方法调用Messenger.getBinder(),最终是通过IMessenger.Stub的asBinder()返回的IBinder;
客户端:onServiceConnected()里面调用Messenger mService=new Messenger(service)来返回Messenger对象,在构造方法内部会先通过IMessenger.Stub.asInterface(target)来创建IMessenger实例mTarget;
交互:客户端在通过send()发送消息时,会通过mTarget的send()方法,经过binder驱动处理,会调用到IMessenger.Stub的onTransact()方法,最终会调用服务端的MessengerImpl的send()方法,继而通过Handler来sendMessage(),最后服务端的Handler来handleMessage();
四.与 AIDL 比较:
执行 IPC 时,使用 Messenger 要比使用 AIDL 实现更加简单,因为 Messenger 会将所有服务调用排入队列,而纯粹的 AIDL 接口会同时向服务发送多个请求,服务随后必须应对多线程处理。
对于大多数应用,服务不需要执行多线程处理,因此使用 Messenger 可让服务一次处理一个调用。如果服务必须执行多线程处理,则应使用 AIDL 来定义接口。