Messenger可以翻译成信使,通过它可以在不同进程间传递Message对象有了它就可以轻松实现进程间的数据传递了。
Messenger使用的方法相对AIDL比较简单,它对AIDL做了一层封装是的我们不需要像采用AIDL那样去实现进程通信那么麻烦,可以看看他的源码有AIDL的迹象。
public final class Messenger implements Parcelable {
private final IMessenger mTarget;
public Messenger(Handler target) {
mTarget = target.getIMessenger();
}
public void send(Message message) throws RemoteException {
mTarget.send(message);
}
public IBinder getBinder() {
return mTarget.asBinder();
}
public boolean equals(Object otherObj) {
if (otherObj == null) {
return false;
}
try {
return mTarget.asBinder().equals(((Messenger)otherObj)
.mTarget.asBinder());
} catch (ClassCastException e) {
}
return false;
}
public int hashCode() {
return mTarget.asBinder().hashCode();
}
public int describeContents() {
return 0;
}
public void writeToParcel(Parcel out, int flags) {
out.writeStrongBinder(mTarget.asBinder());
}
public static final Parcelable.Creator<Messenger> CREATOR
= new Parcelable.Creator<Messenger>() {
public Messenger createFromParcel(Parcel in) {
IBinder target = in.readStrongBinder();
return target != null ? new Messenger(target) : null;
}
public Messenger[] newArray(int size) {
return new Messenger[size];
}
};
public static void writeMessengerOrNullToParcel(Messenger messenger,
Parcel out) {
out.writeStrongBinder(messenger != null ? messenger.mTarget.asBinder()
: null);
}
public static Messenger readMessengerOrNullFromParcel(Parcel in) {
IBinder b = in.readStrongBinder();
return b != null ? new Messenger(b) : null;
}
public Messenger(IBinder target) {
mTarget = IMessenger.Stub.asInterface(target);
}
}
首先我们需要新建一个Service来处理客户端的请求,同时声明一个Handler作为参数来创建一个Messenger,然后通过getBinder()方法返回Binder。
public class MessageService extends Service {
private Messenger mMessenger = new Messenger(new Handler() {
@Override
public void handleMessage(Message msgFromClient) {
super.handleMessage(msgFromClient);
Message msgToTarget = Message.obtain(msgFromClient);
msgToTarget.what = 0;
try {
Thread.sleep(2000);
msgToTarget.arg1 = msgFromClient.arg1 + msgFromClient.arg2;
msgFromClient.replyTo.send(msgToTarget);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (RemoteException e) {
e.printStackTrace();
}
}
});
@Nullable
@Override
public IBinder onBind(Intent intent) {
return mMessenger.getBinder();
}
}
里面的逻辑是简单的将客户端传来的Message中的arg1和arg2的值相加并将结果返回给Message对应的replyTo这个Messenger,并通过send将服务端的Message返回给客户端。
然后在客户端处理:首先需要bindService来绑定这个Service,然后通过IBinder生成一个Messenger对象,这个Messenger对象就可以将需要处理的数据封装到Message然后send到Service去。
Messenger mMessenger = new Messenger(new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
Log.w("Jayuchou", "--- 从异步线程中读取到数据 --- " + msg.arg1);
}
});
Messenger mService;
ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mService = new Messenger(service);
Log.w("Jayuchou", "-- Connected success --");
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.w("Jayuchou", "-- Connected dismiss --");
mService = null;
}
};
然后调用的地方方式为:
Message msgFromClient = Message.obtain(null, 0, 1, 2);
msgFromClient.replyTo = mMessenger;
try {
mService.send(msgFromClient);
} catch (RemoteException e) {
e.printStackTrace();
}
将数据封装Message中,并且Message中的replyTo指定服务端中要将结果回调的Messenger对象。
msgFromClient.replyTo.send(msgToTarget);
我们可以看到Service中有这么一句代码,其中的replyTo就是我们在客户端传进去的Messenger,这时候调用send方法就可以将服务端的也就是另一个进程的数据传到想要用的进程然后采用Messenger进行接收,我们可以跟Handler用法类似的使用即可。Messenger是一个轻量级的AIDL,一次一个处理请求。