IPC通信中,有一个关于Messenger的,前几天用了一下,下面给总结一下使用心得及具体用法。
首先,Messenger底层是基于AIDL封装的一个轻量级的IPC方案;
其次,Messenger的用法基于Handler,从安全性能上来说,它是线程安全的;
针对于处理高并发的问题,可能它就不适用了,这里可以参考Messenger的源码,它支持一次处理一个请求,这个时候不用考虑线程同步,同时也就不支持高并发场景了;
除此之外,Messenger不支持RPC(Remote Procedure Call)—远程过程调用协议);
针对于上述情况,我们可以总结下Messenger的应用场景:
一对多的无高并发的即时通讯,同时没有RPC需求。
下面来讲下具体的用法:
首先创建一个Service,创建一个Handler(用来创建一个Messenger对象),然后在Service的onBind方法中,返回这个Messenger对象的Binder对象,下面贴一下代码
public class MyMessengerIntentService extends IntentService {
private static final String TAG = MyMessengerIntentService.class.getSimpleName();
private static final Messenger mMessenger = new Messenger(new MyMessengerHandler());
public MyMessengerIntentService() {
super(" MyMessengerIntentService");
}
@Override
protected void onHandleIntent(@Nullable Intent intent) {
Log.d(TAG, "onHandleIntent: ");
}
private static class MyMessengerHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_FROM_MESSENGER_CLIENT:
Log.d(TAG, "handleMessage: receive msg from client:" +
msg.getData().get("msg"));
Messenger client = msg.replyTo;
Message replyMsg = Message.obtain(null, MSG_FROM_MESSENGER_SERVICE);
Bundle bundle = new Bundle();
bundle.putString("reply", "I am service ,I have receive your message
,thanks!");
replyMsg.setData(bundle);
try {
client.send(replyMsg);
} catch (RemoteException e) {
e.printStackTrace();
}
break;
default:
super.handleMessage(msg);
}
}
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return mMessenger.getBinder();
}
@Override
public void onDestroy() {
super.onDestroy();
}
}
这里用到了IntentService,其实跟Service没什么区别,只是在Service中进行耗时操作的时候,可以将耗时操作的逻辑放到onHandIntent方法体中。
然后来看看客户端的代码:
public class MessengerActivity extends Activity {
public static final String TAG = MessengerActivity.class.getSimpleName();
private Messenger mService = null;
private MessengerService.MyBinder binder = null;
private ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mService = new Messenger(service);
Message message = Message.obtain(null, MSG_FROM_MESSENGER_CLIENT);
Bundle bundle = new Bundle();
bundle.putString("msg", "hello, i am client");
message.setData(bundle);
message.replyTo = messenger;
try {
mService.send(message);
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
private Messenger messenger = new Messenger(new MessengerHandler());
private static class MessengerHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_FROM_MESSENGER_SERVICE:
Log.d(TAG, "receive msg from service: " +
msg.getData().get("reply"));
break;
default:
super.handleMessage(msg);
}
}
}
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_a);
Intent intent = new Intent(this, MyMessengerIntentService.class);
bindService(intent, connection, Context.BIND_AUTO_CREATE);
}
@Override
protected void onDestroy() {
//解绑
unbindService(connection);
super.onDestroy();
}
主要的代码逻辑,绑定Service,通过Service返回的IBinder对象,创建Messenger对象,用于给服务端发送消息。
其次就是通过Handler创建一个对象,用于创建Messenger对象,这个对象用来获取服务端返回的消息。这一步用来做服务端回复消息,可以看下上面Service中,加了回复的逻辑。
最后看下打印,这是服务器的打印,由于我采用了多进程模式模拟了进程间通信,可以看到进程名字不同
03-18 14:56:10.534 17433-17433/com.dhc.jstestdemo:remote2 D/MyMessengerIntentService: handleMessage: receive msg from client:hello, i am client
然后是客户端的打印
03-18 14:56:10.565 17420-17420/com.dhc.jstestdemo D/MessengerActivity: receive msg from service: I am service ,I have receive your message ,thanks!
能注意到的是,两个进程名字不一样,一个是com.dhc.jstestdemo,一个是com.dhc.jstestdemo:remote2。
到这里,一个Messenger的用法就讲解完毕了,对于为什么不支持RPC,以及为什么不能用于高并发场景,大家可以仔细查看源码。