Activity與Service通信

http://www.cnblogs.com/ruiati/archive/2013/10/20/3379380.html

繼承Binder類

這個方式只有當你的Acitivity和Service處于同一個Application和進程時,才可以用,比如你后臺有一個播放背景音樂的Service,這時就可以用這種方式來進行通信。

用例子來說明其使用方法:

1. 來看Service的寫法:

publicclassLocalServiceextendsService?{

//?實例化自定義的Binder類

privatefinalIBinder?mBinder?=newLocalBinder();

//?隨機數的生成器

privatefinalRandom?mGenerator?=newRandom();

/**

*?自定義的Binder類,這個是一個內部類,所以可以知道其外圍類的對象,通過這個類,讓Activity知道其Service的對象

*/

publicclassLocalBinderextendsBinder?{

LocalService?getService()?{

//?返回Activity所關聯的Service對象,這樣在Activity里,就可調用Service里的一些公用方法和公用屬性

returnLocalService.this;

}

}

@Override

publicIBinder?onBind(Intent?intent)?{

returnmBinder;

}

/**?public方法,Activity可以進行調用?*/

publicintgetRandomNumber()?{

returnmGenerator.nextInt(100);

}

}

在Service里定義一個內部類,Binder的子類,通過這個類,把Service的對象傳給Activity,這樣Activity就可以調用Service里的公用方法和公用屬性了,但這種方式,一定要在同一個進程和同一個Application里。

2. 再看相應Activity的代碼:

publicclassBindingActivityextendsActivity?{

LocalService?mService;

booleanmBound?=false;

@Override

protectedvoidonCreate(Bundle?savedInstanceState)?{

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

}

@Override

protectedvoidonStart()?{

super.onStart();

//?綁定Service,綁定后就會調用mConnetion里的onServiceConnected方法

Intent?intent?=newIntent(this,?LocalService.class);

bindService(intent,?mConnection,?Context.BIND_AUTO_CREATE);

}

@Override

protectedvoidonStop()?{

super.onStop();

//?解綁Service,這樣可以節(jié)約內存

if(mBound)?{

unbindService(mConnection);

mBound?=false;

}

}

/**?用戶點擊button,就讀取Service里的隨機數?*/

publicvoidonButtonClick(View?v)?{

if(mBound)?{

//?用Service的對象,去讀取隨機數

intnum?=?mService.getRandomNumber();

Toast.makeText(this,"number:?"+?num,?Toast.LENGTH_SHORT).show();

}

}

/**?定交ServiceConnection,用于綁定Service的*/

privateServiceConnection?mConnection?=newServiceConnection()?{

@Override

publicvoidonServiceConnected(ComponentName?className,

IBinder?service)?{

//?已經綁定了LocalService,強轉IBinder對象,調用方法得到LocalService對象

LocalBinder?binder?=?(LocalBinder)?service;

mService?=?binder.getService();

mBound?=true;

}

@Override

publicvoidonServiceDisconnected(ComponentName?arg0)?{

mBound?=false;

}

};

}

這里就是通過IBinder來得到LocalService對象,再去調用其Public方法。

使用Messenger

上面的方法只能在同一個進程里才能用,如果要與另外一個進程的Service進行通信,則可以用Messenger。

其實實現IPC的方式,還有AIDL,但推薦使用Messenger,有兩點好處:

1. 使用Messenger方式比使用AIDL的方式,實現起來要簡單很多

2. 使用Messenger時,所有從Activity傳過來的消息都會排在一個隊列里,不會同時請求Service,所以是線程安全的。如果你的程序就是要多線程去訪問Service,就可以用AIDL,不然最好使用Messenger的方式。

不過,其實Messenger底層用的就是AIDL實現的,看一下實現方式,先看Service的代碼:

publicclassMessengerServiceextendsService?{

/**?用于Handler里的消息類型?*/

staticfinalintMSG_SAY_HELLO?=1;

/**

*?在Service處理Activity傳過來消息的Handler

*/

classIncomingHandlerextendsHandler?{

@Override

publicvoidhandleMessage(Message?msg)?{

switch(msg.what)?{

caseMSG_SAY_HELLO:

Toast.makeText(getApplicationContext(),"hello!",?Toast.LENGTH_SHORT).show();

break;

default:

super.handleMessage(msg);

}

}

}

/**

*?這個Messenger可以關聯到Service里的Handler,Activity用這個對象發(fā)送Message給Service,Service通過Handler進行處理。

*/

finalMessenger?mMessenger?=newMessenger(newIncomingHandler());

/**

*?當Activity綁定Service的時候,通過這個方法返回一個IBinder,Activity用這個IBinder創(chuàng)建出的Messenger,就可以與Service的Handler進行通信了

*/

@Override

publicIBinder?onBind(Intent?intent)?{

Toast.makeText(getApplicationContext(),"binding",?Toast.LENGTH_SHORT).show();

returnmMessenger.getBinder();

}

}

再看一下Activity的代碼:

publicclassActivityMessengerextendsActivity?{

/**?向Service發(fā)送Message的Messenger對象?*/

Messenger?mService?=null;

/**?判斷有沒有綁定Service?*/

booleanmBound;

privateServiceConnection?mConnection?=newServiceConnection()?{

publicvoidonServiceConnected(ComponentName?className,?IBinder?service)?{

//?Activity已經綁定了Service

//?通過參數service來創(chuàng)建Messenger對象,這個對象可以向Service發(fā)送Message,與Service進行通信

mService?=newMessenger(service);

mBound?=true;

}

publicvoidonServiceDisconnected(ComponentName?className)?{

mService?=null;

mBound?=false;

}

};

publicvoidsayHello(View?v)?{

if(!mBound)return;

//?向Service發(fā)送一個Message

Message?msg?=?Message.obtain(null,?MessengerService.MSG_SAY_HELLO,0,0);

try{

mService.send(msg);

}catch(RemoteException?e)?{

e.printStackTrace();

}

}

@Override

protectedvoidonCreate(Bundle?savedInstanceState)?{

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

}

@Override

protectedvoidonStart()?{

super.onStart();

//?綁定Service

bindService(newIntent(this,?MessengerService.class),?mConnection,

Context.BIND_AUTO_CREATE);

}

@Override

protectedvoidonStop()?{

super.onStop();

//?解綁

if(mBound)?{

unbindService(mConnection);

mBound?=false;

}

}

}

注意:以上寫的代碼只能實現從Activity向Service發(fā)送消息,如果想從Service向Activity發(fā)送消息,只要把代碼反過來寫就可以了。

使用AIDL

這個方法略,如果知道上面兩種方法,這個方法基本很少會用到。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容