onCreate()方法只會在Service第一次被創(chuàng)建的時候調(diào)用,如果當(dāng)前Service已經(jīng)被創(chuàng)建過了,不管怎樣調(diào)用startService()方法,onCreate()方法都不會再執(zhí)行。
Service和Activity通信
Activity通過binder來啟動或停止service中的任務(wù),并監(jiān)聽service中任務(wù)的進(jìn)度。代碼如下:
OnProgressListener
public interface OnProgressListener {
void onProgress(int progress);
}
MyService
public class MyService extends Service {
private final String TAG = "MyService";
private int progress = 0;
private MyBinder mBinder = new MyBinder();
@Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "onCreate() executed");
}
@Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
Log.d(TAG, "onStart() executed");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "onStartCommand() executed");
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
super.onDestroy();
Log.d(TAG, "onDestroy() executed");
}
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
@Override
public boolean onUnbind(Intent intent) {
Log.d(TAG, "onUnbind() executed");
return super.onUnbind(intent);
}
class MyBinder extends Binder {
/**
* 更新進(jìn)度的回調(diào)接口
*/
private OnProgressListener onProgressListener;
public void startDownload() {
Log.d(TAG, "startDownload() executed");
// 執(zhí)行具體的下載任務(wù)
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
progress++;
//進(jìn)度發(fā)生變化通知調(diào)用方
if (onProgressListener != null) {
onProgressListener.onProgress(progress);
}
}
}
public void stopDownload() {
Log.d(TAG, "stopDownload() executed");
// 執(zhí)行具體的下載任務(wù)
}
/**
* 注冊回調(diào)接口的方法,供外部調(diào)用
*
* @param onProgressListener
*/
public void setOnProgressListener(OnProgressListener onProgressListener) {
this.onProgressListener = onProgressListener;
}
}
}
MainActivity中
public class MainActivity extends AppCompatActivity {
MyService.MyBinder myBinder = null;
Button btn_start,btn_stop;
private String Tag = "MyService";
private ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
myBinder = (MyService.MyBinder) service;
myBinder.setOnProgressListener(new OnProgressListener() {
@Override
public void onProgress(int progress) {
Log.i(Tag,"progress: "+progress);
}
});
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn_start = (Button)findViewById(R.id.btn_start);
btn_stop = (Button)findViewById(R.id.btn_stop);
Intent bindIntent = new Intent(this, MyService.class);
bindService(bindIntent, connection, BIND_AUTO_CREATE);
btn_start.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
myBinder.startDownload();
}
});
btn_stop.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
myBinder.stopDownload();
}
});
}
}
bindService和startService的區(qū)別
- 生命周期的區(qū)別:
startService,【onCreate()- >onStartCommand()->startService()->onDestroy()】
補充說明:其中沒有onStart(),主要是被onStartCommand()方法給取代了,onStart方法不推薦使用了;
bindService(),【onCreate()->onBind()->onUnbind()->onDestroy()】
補充說明:傳遞給bindService()的Intent對象會傳遞給onBind(),傳遞給unbindService()的Intent對象會傳遞給onUnbind()方法。調(diào)用順序為:onCreate --> onBind(只一次,不可多次綁定) --> onUnbind --> onDestory。 - 調(diào)用者和服務(wù)者之間的關(guān)系:
startService()的調(diào)用,調(diào)用者和服務(wù)之間沒有聯(lián)系,即使調(diào)用者退出了,服務(wù)依然在進(jìn)行。
bindService()調(diào)用者和綁定者綁在一起,調(diào)用者一旦退出服務(wù)也就終止了。
注意:BroadcastReceiver只能通過startService啟動Service,因為廣播本身生命周期很短,bind的話沒有意義。 - 關(guān)于多次調(diào)用:
多次調(diào)用startService,該Service只能被創(chuàng)建一次,即該Service的onCreate方法只會被調(diào)用一次。但是每次調(diào)用startService,onStartCommand方法都會被調(diào)用。Service的onStart方法在API 5時被廢棄,替代它的是onStartCommand方法。
第一次執(zhí)行bindService時,onCreate和onBind方法會被調(diào)用,但是多次執(zhí)行bindService時,onCreate和onBind方法并不會被多次調(diào)用,即并不會多次創(chuàng)建服務(wù)和綁定服務(wù)。 - 既使用startService又使用bindService的情況
如果一個Service又被啟動又被綁定,則該Service會一直在后臺運行。首先不管如何調(diào)用,onCreate始終只會調(diào)用一次。對應(yīng)startService調(diào)用多少次,Service的onStartCommand方法便會調(diào)用多少次。Service的終止,需要unbindService和stopService同時調(diào)用才行。不管startService與bindService的調(diào)用順序,如果先調(diào)用unbindService,此時服務(wù)不會自動終止,再調(diào)用stopService之后,服務(wù)才會終止;如果先調(diào)用stopService,此時服務(wù)也不會終止,而再調(diào)用unbindService或者之前調(diào)用bindService的Context不存在了(如Activity被finish的時候)之后,服務(wù)才會自動停止。
那么,什么情況下既使用startService,又使用bindService呢?
如果你只是==想要啟動一個后臺服務(wù)長期進(jìn)行某項任務(wù)同時還想要與正在運行的Service取得聯(lián)系,那么有兩種方法:一種是使用broadcast,另一種是使用bindService。前者的缺點是如果交流較為頻繁,容易造成性能上的問題,而后者則沒有這些問題。因此,這種情況就需要startService和bindService一起使用了。
另外,如果你的服務(wù)只是公開一個遠(yuǎn)程接口,供連接上的客戶端(Android的Service是C/S架構(gòu))遠(yuǎn)程調(diào)用執(zhí)行方法,這個時候你可以不讓服務(wù)一開始就運行,而只是bindService,這樣在第一次bindService的時候才會創(chuàng)建服務(wù)的實例運行它,這會節(jié)約很多系統(tǒng)資源,特別是如果你的服務(wù)是遠(yuǎn)程服務(wù),那么效果會越明顯(當(dāng)然在Servcie創(chuàng)建的是偶會花去一定時間,這點需要注意) - 銷毀 service
Bind Service -> Unbind Service
Start Service -> Stop Service
Bind Service + Start Service -> Unbind Service + Stop Service(無順序區(qū)別)
==注意點==
onServiceDisconnected 會在程序意外退出時才會調(diào)用