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ì)用到。