前言—— 生活依旧如此美好 秋不白
之前有次面试遇到这样一个问题。如何使用Handler完成Activity和Service间通信?可惜之前对这方面没有进一步去了解,没有回答好。
当然是使用Messenger,查看Messenger的构造方法有两个,分别是:
public Messenger(IBinder target) {
mTarget = IMessenger.Stub.asInterface(target);
}
public Messenger(Handler target) {
mTarget = target.getIMessenger();
}
答案就很明显了,使用Messenger。
服务中以Messenger(Handler target)来创建信使,在onBind方法中返回IBinder对象
Activity中以bindService来绑定Service,在onServiceConnected()中获取Service 的IBinder,创建Messenger对象,于是这个信使就持有了Service中的Handler,就可以在Activity中发送消息给Service了,并且在Message的replyTo属性上可以赋值Messenger对象,Activity和Service通过Messenger完成互相通信,分析就到这里,再往下我也不懂了,也没有太大的必要。
通过Messenger的第一个构造方法,也可以看出,底层实现是AIDL,Messenger对AIDL做了封装,局限性:一次处理一个请求,如果有大量消息同时发送到服务端,还是得使用AIDL。
插入部分Activity和Service的代码:
Activity(客户端):
public void openIPC(View view) {
Intent intent = new Intent(this,MyService.class);
bindService(intent,conn, Context.BIND_AUTO_CREATE);
}
private ServiceConnection conn = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Messenger messenger = new Messenger(service);
Message msg = Message.obtain();
msg.what = 1;
Bundle bundle = new Bundle();
bundle.putString("data","服务端你好,我是客户端");
msg.setData(bundle);
msg.replyTo = new Messenger(new ClientHandler());
try {
messenger.send(msg);
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
private static class ClientHandler extends Handler{
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
Log.d("MainActivity"," 收到服务端发送的消息 " + msg.getData().getString("data"));
}
}
Service(服务端):
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
return mMessenger.getBinder();
}
private static class MyHandlre extends Handler {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case 1:
Messenger client = msg.replyTo;
Log.d("MyService"," 收到客户端发送的消息 " + msg.getData().getString("data"));
Message msgService = Message.obtain();
Bundle bundle = new Bundle();
bundle.putString("data"," Hi. 客户端你好,我是服务端");
msgService.setData(bundle);
try {
client.send(msgService);
} catch (RemoteException e) {
e.printStackTrace();
}
break;
case 2:
break;
default:
break;
}
}
}
private final Messenger mMessenger = new Messenger(new MyHandlre());
别忘了在清单文件中给Service指定进程,开启多进程,更好的体现Messenger进程间通信。分析就到这里,可以去看看Handler 源码,AIDL。生活依旧如此美好,一起加油!