Service完全解析(二)
1.Messenger介紹
2.使用Messenger實現跨進程通信
3.相關知識點及注意事項
Messenger扮演信使的角色,它指向一個Handler,可以通過這個信使向其指向的Handler傳遞數據。
要實現跨進程通信,其實質是在不同進程間傳遞Messenger。客戶端向服務器端發送數據,只要得到服務器端的信使,然後調用send()方法即可;服務器端向客戶端發送數據也一樣,先得到客戶端的信使,調用send()方法即可。
服務器端向客戶端傳遞信使的方法是:
(1)創建Messenger對象;
(2)在onBind()方法中返回Messenger.getBind();
(3)客戶端在onServiceConnected()方法中以new Messenger(IBinder對象)的方法獲取到一個Messenger,這個Messenger就是服務器端的信使。
客戶端向服務器端傳遞信使的方法是:
(1)創建一個Messenger對象;
(2)創建一個Message對象,這個對象是要發送給服務器的;
(3)將上面創建的Messenger對象給Message對象:Message.replyTo = Messenger;
(4)將這個Message對象發送給服務器端即可。
代碼分析:
服務器端代碼:
public MessageService() {
/*創建一個Handler處理來自客戶端的Message*/
mHandler = new Handler(){
@Override
public void handleMessage(Message msgfromclient){
Log.v("out","當前線程:"+android.os.Process.myPid()+"收到客戶端的數據爲:"+msgfromclient.what);
/*得到來自客戶端的信使*/
Messenger messengerfromclient = msgfromclient.replyTo;
Message messagetoclient = Message.obtain(null,123456789);
try {
messengerfromclient.send(messagetoclient);
} catch (RemoteException e) {
e.printStackTrace();
}
}
};
/*根據上面的Handler生成一個Messenger對象,Messenger:信使,指向一個Handler,可以通過
* 這個Messenger來將Message發給其指向的Handler處理*/
mMessenger = new Messenger(mHandler);
}
@Override
public IBinder onBind(Intent intent) {
/*通過這一步操作將Messenger返給客戶端*/
return mMessenger.getBinder();
}
客戶端代碼:
private ServiceConnection conn;
private Messenger mMessengerService,mMessengerClient;
private Message msgToService;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_message_service);
mMessengerClient = new Messenger(new Handler(){
@Override
public void handleMessage(Message msgfromservice){
Log.v("out","收到了來自服務器端的數據:"+msgfromservice.what);
}
});
/*爲了能讓服務器也給客戶端發送數據,我們需要將客戶端的信使傳遞給服務器端,服務器端將信使傳遞給
* 客戶端的方式是通過Binder,客戶端將信使傳遞給服務器端的方式是將信使封裝到Message對象中*/
msgToService = Message.obtain(null,123321);
msgToService.replyTo = mMessengerClient;
/*首先創建ServiceConnection,並從中獲取到服務器端的Messenger*/
conn = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
/*得到的是服務端的信使,我們通過這個信使將數據發給服務端*/
mMessengerService = new Messenger(service);
try {
mMessengerService.send(msgToService);
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
bindService(new Intent(MessageServiceActivity.this, MessageService.class),conn,this.BIND_AUTO_CREATE);
}
@Override
public void onDestroy(){
super.onDestroy();
unbindService(conn);
}
其他相關知識點
(1)Service運行在UI線程中的。
(1)unBindService()後Service會調用onDestroy()方法,如果Service新開了線程,此時線程仍會執行,如果想關閉,可以在onDestroy()中設置標誌。同時,由於onServiceConnected()方法中有Service的Binder的引用,此時仍然可以調用Service中的方法。