Activity與Service通信

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

繼承Binder類

這個(gè)方式只有當(dāng)你的Acitivity和Service處于同一個(gè)Application和進(jìn)程時(shí),才可以用,比如你后臺(tái)有一個(gè)播放背景音樂的Service,這時(shí)就可以用這種方式來進(jìn)行通信。

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

1. 來看Service的寫法:

publicclassLocalServiceextendsService?{

//?實(shí)例化自定義的Binder類

privatefinalIBinder?mBinder?=newLocalBinder();

//?隨機(jī)數(shù)的生成器

privatefinalRandom?mGenerator?=newRandom();

/**

*?自定義的Binder類,這個(gè)是一個(gè)內(nèi)部類,所以可以知道其外圍類的對(duì)象,通過這個(gè)類,讓Activity知道其Service的對(duì)象

*/

publicclassLocalBinderextendsBinder?{

LocalService?getService()?{

//?返回Activity所關(guān)聯(lián)的Service對(duì)象,這樣在Activity里,就可調(diào)用Service里的一些公用方法和公用屬性

returnLocalService.this;

}

}

@Override

publicIBinder?onBind(Intent?intent)?{

returnmBinder;

}

/**?public方法,Activity可以進(jìn)行調(diào)用?*/

publicintgetRandomNumber()?{

returnmGenerator.nextInt(100);

}

}

在Service里定義一個(gè)內(nèi)部類,Binder的子類,通過這個(gè)類,把Service的對(duì)象傳給Activity,這樣Activity就可以調(diào)用Service里的公用方法和公用屬性了,但這種方式,一定要在同一個(gè)進(jìn)程和同一個(gè)Application里。

2. 再看相應(yīng)Activity的代碼:

publicclassBindingActivityextendsActivity?{

LocalService?mService;

booleanmBound?=false;

@Override

protectedvoidonCreate(Bundle?savedInstanceState)?{

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

}

@Override

protectedvoidonStart()?{

super.onStart();

//?綁定Service,綁定后就會(huì)調(diào)用mConnetion里的onServiceConnected方法

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

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

}

@Override

protectedvoidonStop()?{

super.onStop();

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

if(mBound)?{

unbindService(mConnection);

mBound?=false;

}

}

/**?用戶點(diǎn)擊button,就讀取Service里的隨機(jī)數(shù)?*/

publicvoidonButtonClick(View?v)?{

if(mBound)?{

//?用Service的對(duì)象,去讀取隨機(jī)數(shù)

intnum?=?mService.getRandomNumber();

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

}

}

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

privateServiceConnection?mConnection?=newServiceConnection()?{

@Override

publicvoidonServiceConnected(ComponentName?className,

IBinder?service)?{

//?已經(jīng)綁定了LocalService,強(qiáng)轉(zhuǎn)IBinder對(duì)象,調(diào)用方法得到LocalService對(duì)象

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

mService?=?binder.getService();

mBound?=true;

}

@Override

publicvoidonServiceDisconnected(ComponentName?arg0)?{

mBound?=false;

}

};

}

這里就是通過IBinder來得到LocalService對(duì)象,再去調(diào)用其Public方法。

使用Messenger

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

其實(shí)實(shí)現(xiàn)IPC的方式,還有AIDL,但推薦使用Messenger,有兩點(diǎn)好處:

1. 使用Messenger方式比使用AIDL的方式,實(shí)現(xiàn)起來要簡單很多

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

不過,其實(shí)Messenger底層用的就是AIDL實(shí)現(xiàn)的,看一下實(shí)現(xiàn)方式,先看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);

}

}

}

/**

*?這個(gè)Messenger可以關(guān)聯(lián)到Service里的Handler,Activity用這個(gè)對(duì)象發(fā)送Message給Service,Service通過Handler進(jìn)行處理。

*/

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

/**

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

*/

@Override

publicIBinder?onBind(Intent?intent)?{

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

returnmMessenger.getBinder();

}

}

再看一下Activity的代碼:

publicclassActivityMessengerextendsActivity?{

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

Messenger?mService?=null;

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

booleanmBound;

privateServiceConnection?mConnection?=newServiceConnection()?{

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

//?Activity已經(jīng)綁定了Service

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

mService?=newMessenger(service);

mBound?=true;

}

publicvoidonServiceDisconnected(ComponentName?className)?{

mService?=null;

mBound?=false;

}

};

publicvoidsayHello(View?v)?{

if(!mBound)return;

//?向Service發(fā)送一個(gè)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;

}

}

}

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

使用AIDL

這個(gè)方法略,如果知道上面兩種方法,這個(gè)方法基本很少會(huì)用到。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容