前言—— 生活依舊如此美好 秋不白
之前有次面試遇到這樣一個問題。如何使用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。生活依舊如此美好,一起加油!