**Service**
Service與Activity一樣,是Android的四大組件之一。Activity是看得見的,而Service則是看不見的。看得見的Activity一般承擔顯示界面、控制的功能,而Service則承擔后臺任務。而Service與線程的區(qū)別在于,Service是Android的四大組件之一,所以系統(tǒng)不會輕易將其殺死。服務可有其他應用組件啟動,而且即使用戶切換到其他應用,服務仍將在后臺繼續(xù)運行。此外,組件可以綁定到服務,以與之進行交互,甚至是執(zhí)行進程間通信(IPC)。例如,服務可以處理網絡事務、播放音樂、執(zhí)行文件I/O或與內容提供程序交互,而所有這一切均可在后臺進行。
服務基本上分為兩種形式運行:
-?啟動
當應用組件(如Activity)通過調用startService()啟動服務時,服務即處于“啟動”狀態(tài)。一旦啟動,服務即可在后臺無限期運行,即使啟動服務的組件已被銷毀也不受影響。已啟動的服務通常是執(zhí)行單一操作,而且不會將結果返回給調用方。例如,它可能通過網絡下載或上傳文件。操作完成后,服務會自行停止運行。
-?綁定
當應用組件通過bindService()綁定到服務時,服務即處于“綁定”狀態(tài)。綁定服務提供了一個客戶端-服務器接口,允許組件與服務進行交互、發(fā)送請求、獲取結果,甚至是利用進程間通信(IPC)跨進程執(zhí)行這些操作。僅當與另一個應用組件綁定時,綁定服務才會運行。多個組件可以同時綁定到該服務,但全部取消綁定后,該服務即會被銷毀。
##startService()
????1.啟動后,服務就和啟動它的組件沒關系
????2.如果服務被意外,隔段時間會自動重啟,隨著被殺死的次數增多,間隔時間越來越久
????3.生命周期方法在主線程調用
????4.服務要和子線程配合
????5.生命周期:onCreate()-->onStartCommand()--onDestroy();,如果重復啟動一個service,onCreate()方法不會再調用,直接onStartCommand()
如果Service還沒有運行,則android先調用onCreate()然后調用onStart();
如果Service已經運行,則只調用onStart(),所以一個Service的onStart方法可能會重復調用多次。?調用stopService的時候直接onDestroy,
如果是調用者自己直接退出而沒有調用stopService的話,Service會一直在后臺運行。
該Service的調用者再啟動起來后可以通過stopService關閉Service。
所以調用startService的生命周期為:onCreate --> onStart(可多次調用) --> onDestroy
對于bindService()綁定回調Service會經歷:
context.bindService()->onCreate()->onBind()->Service running-->onUnbind() -> onDestroy() ->Service stop
onBind將返回給客戶端一個IBind接口實例,IBind允許客戶端回調服務的方法,比如得到Service運行的狀態(tài)或其他操作。
這個時候把調用者(Context,例如Activity)會和Service綁定在一起,Context退出了,
Srevice就會調用onUnbind->onDestroy相應退出。
所以調用bindService的生命周期為:onCreate --> onBind(只一次,不可多次綁定) --> onUnbind --> onDestory。
一但銷毀activity它就結束,如果按home把它放到后臺,那他就不退出。
在Service每一次的開啟關閉過程中,只有onStart可被多次調用(通過多次startService調用),其他onCreate,onBind,onUnbind,onDestory在一個生命周期中只能被調用一次。
Service 類兩種啟動方法:
1.?Context.startService():
在同一個應用任何地方調用 startService() 方法就能啟動 Service 了,然后系統(tǒng)會回調 Service 類的 onCreate() 以及 onStart() 方法。這樣啟動的 Service 會一直運行在后臺,直到 Context.stopService() 或者 selfStop() 方法被調用。
另外如果一個 Service 已經被啟動,其他代碼再試圖調用 startService() 方法,是不會執(zhí)行 onCreate() 的,但會重新執(zhí)行一次 onStart() 。
2.?Context.bindService()?:
將?Service 和調用 Service 的客戶類綁起來,如果調用這個客戶類被銷毀,Service 也會被銷毀。用這個方法的一個好處是,bindService() 方法執(zhí)行后 Service 會回調上邊提到的 onBind() 方發(fā),你可以從這里返回一個實現了 IBind 接口的類,在客戶端操作這個類就能和這個服務通信了,比如得到 Service 運行的狀態(tài)或其他操作。如果 Service 還沒有運行,使用這個方法啟動 Service 就會 onCreate() 方法而不會調用 onStart()。
** 2.工作中遇到的安卓下線程與服務的區(qū)別:**
????1.進程和服務的定義
????線程(thread):線程是程序運行的最小單元,是分配cpu的基本單位,本應用程序托管。
????服務(service);是android的一種機制,對應的service是運行在主線程上的,它是由系統(tǒng)進程托管。他們之間的通信類似于client和server,是一種輕量級的ipc通信,這種通信的載體是binder,它是在linux層交換信息的一種ipc;
1)在應用中,如果是長時間的在后臺運行,而且不需要交互的情況下,使用服務。
同樣是在后臺運行,不需要交互的情況下,如果只是完成某個任務,之后就不需要運行,而且可能是多個任務,需要長時間運行的情況下使用線程。
2)如果任務占用CPU時間多,資源大的情況下,要使用線程。
3)最優(yōu)的使用方法
????????????創(chuàng)建并啟動一個service,在Service里面創(chuàng)建、運行并控制該Thread(因為任何Activity都可以控制同一個Service,而系統(tǒng)只會創(chuàng)建一個對應的Service的實例)還有個辦法是使用IntentService,它里面自帶了子線程,使用它就不用創(chuàng)建新線程了。
但由于是單個的worker thread,所以任務需要排隊,不適合大多數的多任務情況。
最后可以把Service想象成一種消息服務,而你可以在任何有Context的地方調用Context.startservice、Context.stopservice、Context.bindService,Context.unbindService,來控制它,也可以在Service里注冊BroadcastReceiver,在其他地方通過發(fā)broadcast來控制它。
生命周期
1)startService生命周期
oncreate()------onStartCommand()-----onDestroy()
如果重復啟動一個服務,oncreate()只走一次,只調用onStartCommand()
2)bindService生命周期
oncreate()----onBind()----onUnBind()
綁定后跟組件生命周期綁定
3)混合啟動生命周期
1.先啟動后綁定
oncreate()---onStartCommand()----onBind()----onUnBind()
解綁后,不會走onDestroy()方法,因為startService還在使用這個服務
2.先綁定后啟動
oncreate()----onBind()----onStartCommand()----onUnBind()----onDestroy()
方法
使用intent跳轉
starteService()啟動服務
stopeService()停止服務
bindService()綁定服務,需要三個參數,第一個是intent,第二個參數為服務連接器ServiceConnection,第三個參數BIND_AUTO_CREATE
unBindService()解綁服務
通信
service---->Activity
在service中,寫一個內部類繼承Binder,在內部類寫一個方法,在onBind()方法返回我們得內部類。在Activity頁面,我們bindService()服務連接器回調中,在onServiceConnected強制轉換對應的service,調用服務方法
mConn = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//服務連接成功之后的回調
//IBinder service,這個對象是要綁定的服務里面的onBind()的返回值
MyService.MyBinder binder = (MyService.MyBinder) service;
//這樣就可以調用到服務里面的方法
binder.call();
}
@Override
public void onServiceDisconnected(ComponentName name) {
//服務斷開連接的回調
}
};