如果你需要你的service與遠(yuǎn)程進(jìn)程通信,那么你可以使用一個(gè)Messenger來(lái)為你的service提供接口.此技術(shù)使用不必使用AIDL就能執(zhí)行進(jìn)程間通信(IPC).
下面是如何使用Messenger的概要:
service實(shí)現(xiàn)一個(gè)接收從客戶(hù)端的每個(gè)調(diào)用引起的回調(diào)的Handler.
Handler被用來(lái)創(chuàng)建一個(gè)Messenger對(duì)象(它是Handler的一個(gè)引用).
Messenger創(chuàng)建一個(gè)從service的onBind()返回給客戶(hù)端的IBinder.
客戶(hù)端使用IBinder來(lái)實(shí)例化這個(gè)Messenger(它引用到service的Handler),客戶(hù)端用它來(lái)向service發(fā)送Message.
service在它的Handler中接收每個(gè)消息—具體的,是在handleMessage()方法中.
這此方式下,service中沒(méi)有能讓客戶(hù)端調(diào)用的方法,客戶(hù)端傳送的是service在它的Handler中接收的"消息"(Message對(duì)象).
下面是一個(gè)service使用Messenger接口的例子:
- public class MessengerService extends Service {
- /** 讓service 顯示一個(gè)消息的命令 */
- static final int MSG_SAY_HELLO = 1;
-
- /**
- * 處理從客戶(hù)端來(lái)的消息.
- */
- class IncomingHandler extends Handler {
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case MSG_SAY_HELLO:
- Toast.makeText(getApplicationContext(), "hello!", Toast.LENGTH_SHORT).show();
- break;
- default:
- super.handleMessage(msg);
- }
- }
- }
-
- /**
- * 我們發(fā)布給客戶(hù)端使它能向IncomingHandler 發(fā)送消息的的對(duì)象
- */
- final Messenger mMessenger = new Messenger(new IncomingHandler());
-
- /**
- * 當(dāng)綁定到service,我們返回指向我們的messenger的接口
- */
- @Override
- public IBinder onBind(Intent intent) {
- Toast.makeText(getApplicationContext(), "binding", Toast.LENGTH_SHORT).show();
- return mMessenger.getBinder();
- }
- }
注意Handler中的handleMessage()方法是service接收消息并進(jìn)行處理的地方.
客戶(hù)端所有要做的事就是創(chuàng)建一個(gè)基于service返回的IBinder的Messenger對(duì)象并且使用它的send()發(fā)送一個(gè)消息.如,下面是一個(gè)actvity綁定到service并且傳送MSG_SAY_HELLO命令給service的例子:
- public class ActivityMessenger extends Activity {
- /** 與service通信的Messenger */
- Messenger mService = null;
-
- /** 表明我們是否已綁定到service的標(biāo)記 */
- boolean mBound;
-
- /**
- *與service的主接口交互的類(lèi)
- */
- private ServiceConnection mConnection = new ServiceConnection() {
- public void onServiceConnected(ComponentName className, IBinder service) {
- // 當(dāng)與service的連接已經(jīng)建立時(shí)被調(diào)用.給了我們可以用來(lái)
- //與service交互的對(duì)象.我們正在使用一個(gè)Messenger與service通信,
- // 所以在這里我們從原始IBinder 對(duì)象獲取一個(gè)客戶(hù)端的Messenger的代表
- mService = new Messenger(service);
- mBound = true;
- }
-
- public void onServiceDisconnected(ComponentName className) {
- // 當(dāng)與service的連接意外斷開(kāi)時(shí)被調(diào)用-- 也就是,service的進(jìn)程崩潰了
- mService = null;
- mBound = false;
- }
- };
-
- public void sayHello(View v) {
- if (!mBound) return;
- // 創(chuàng)建并發(fā)送一個(gè)消息給service
- Message msg = Message.obtain(null, MessengerService.MSG_SAY_HELLO, 0, 0);
- try {
- mService.send(msg);
- } catch (RemoteException e) {
- e.printStackTrace();
- }
- }
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
- }
-
- @Override
- protected void onStart() {
- super.onStart();
- // 綁定到service
- bindService(new Intent(this, MessengerService.class), mConnection,
- Context.BIND_AUTO_CREATE);
- }
-
- @Override
- protected void onStop() {
- super.onStop();
- // Unbind from the service
- if (mBound) {
- unbindService(mConnection);
- mBound = false;
- }
- }
- }
注意這個(gè)例子沒(méi)有演示service如何回應(yīng)客戶(hù)端.如果你想讓service回應(yīng)客戶(hù)端,那么你需要在客戶(hù)端也創(chuàng)建一個(gè)Messanger.然后當(dāng)客戶(hù)端接收到onServiceConnected()回調(diào)時(shí),它發(fā)送一個(gè)息給service,這個(gè)消息包含了客戶(hù)端的Messenger對(duì)象,它作為send()方法的replyTo參數(shù).
比較 AIDL
當(dāng)你需要執(zhí)行IPC時(shí),為你的接口使用一個(gè)Messenger比使用AIDL實(shí)現(xiàn)它簡(jiǎn)單,因?yàn)?span style="FONT-FAMILY: Times New Roman, serif">Messenger把所有對(duì)service的調(diào)用入隊(duì)列,一個(gè)純AIDL接口并行發(fā)送請(qǐng)求到service,這樣就必須用多線程來(lái)處理了.
對(duì)于大多數(shù)應(yīng)用,service不需使用多線程,所以使用一個(gè)Messenger允許service在一個(gè)時(shí)刻只處理一個(gè)請(qǐng)求.如果使用多線程對(duì)你的service很重要,那么你應(yīng)使用AIDL來(lái)定義你的接口.
prev
next
本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶(hù)發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)
點(diǎn)擊舉報(bào)。