前言
對于Service這個組件很多同學都會把它跟線程搞混,所以我們有必要先縷清一下基礎知識。
線程:比進程更小的執(zhí)行單元,每個進程可能有多條線程,線程需要放在一個 進程中才能執(zhí)行,線程由程序負責管理,而進程則由系統(tǒng)進行調(diào)度!
多線程的理解:并行執(zhí)行多個條指令,將CPU時間片按照調(diào)度算法分配給各個 線程,實際上是分時執(zhí)行的,只是這個切換的時間很短,用戶感覺到"同時"而已!進程和程序的區(qū)別:程序只是一個靜態(tài)的指令集合,而進程是一個正在系統(tǒng)中活動的指令集合。
那Service跟線程有什么區(qū)別或者聯(lián)系呢。其實一點聯(lián)系都沒有,Service只是一個支持長時間掛在后臺運行的組件而已,在Service中可以開設多線程,其實從層次來說,Service跟線程就不是一個層面上的東西。
在安卓中一般Service都采用一個輪詢的方式進行運行。輪詢(Polling)是一種CPU決策如何提供周邊設備服務的方式,又稱“程控輸入輸出”(Programmed I/O)。輪詢法的概念是:由CPU定時發(fā)出詢問,依序詢問每一個周邊設備是否需要其服務,有即給予服務,服務結(jié)束后再問下一個周邊,接著不斷周而復始。?
Service的啟動方式
Android中使用Service的方式有主要有三種,第三種主要是第一第二種的結(jié)合使用:
BindService()啟動Service
StartService()啟動Service
還有一種不常使用的便是在service啟動之后再去綁定service
創(chuàng)建Service
創(chuàng)建Service的方式非常簡單,Android已經(jīng)將Service封裝成了一個很成熟的類,我們自定義Service只需要繼承Service類即可。下面將給出一段示例代碼,但是值得注意的是,我這里繼承的類并不是Service類,而是IntentService。
這個IntentService看上去可能會有點懵逼,其實該類跟Service類在用法上區(qū)別不大,但是該類在很大程度上優(yōu)化了Service類的使用。使用Service一般都不進行耗時操作,如若超過一秒沒有響應就會發(fā)生報錯,而IntentService則很好的解決了這個問題,該類讓Service進行一些耗時操作成了可能,該類在啟動服務之后會回調(diào)onHandleIntent方法,該方法相當于開多了一個子線程,所有耗時操作都在子線程中完成。該類其實本質(zhì)上就是對Handle的封裝。對于IntentService的具體介紹后面的文章會進一步描述,現(xiàn)在只需要知道創(chuàng)建Service的方法即可。
首先大概得介紹一下這個類里面的每個方法的用途。
onCreate:該方法只會在整個生命周期中調(diào)用一次,在第一次被創(chuàng)建后會立即回調(diào)該方法,后續(xù)無論綁定多少次Service或者啟動多次Service,都不會在調(diào)用這個方法,而是會一直復用一開始創(chuàng)建的Service方法。
onDestory:當Service被關閉時會調(diào)用這個方法,該方法一樣只會調(diào)用一次。
onStartCommand:這個方法只會在startService方式啟動的情況下才會被回調(diào),如若客戶端多次調(diào)用startService,一樣不會創(chuàng)建新的service對象,只會接著服用一開始已經(jīng)創(chuàng)建好的對象。
onBind:這個方法會在通過bindService啟動Service,綁定的時候進行調(diào)用,值得注意的是該方法是可以返回一個Binder對象的,這個Binder對象主要是進行進程之間的通信。
public class ThirdService extends IntentService {
private final static String TAG="ThirdService";
/**
* Creates an IntentService. Invoked by your subclass's constructor.
*
* @param name Used to name the worker thread, important only for debugging.
*/
public ThirdService(String name) {
super(name);
}
public ThirdService() {
super(TAG);
}
public class MyBinder extends Binder{
public String getTag(){
return TAG;
}
}
@Override
protected void onHandleIntent(@Nullable Intent intent) {
Log.d(TAG,"onHandleIntent");
}
@Override
public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
Log.d(TAG,"onStartCommand");
return super.onStartCommand(intent, flags, startId);
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
Log.d(TAG,"onBind");
return new MyBinder();
}
@Override
public void onCreate() {
Log.d(TAG,"onCreate");
super.onCreate();
}
}
?
BindService
第一種直接使用BindService啟動Service:bindService模式下的Service是與調(diào)用者相互關聯(lián)的,可以理解為 "一條繩子上的螞蚱",要死一起死,在bindService后,一旦調(diào)用者銷毀,那么Service也立即終止!
簡單來說就是,當只有一個客戶端綁定了一個service的情況下,當客戶端關閉該service也會被關閉。
如果我們解除與服務的綁定,只需調(diào)用unbindService(),此時onUnbind和onDestory方法將會被調(diào)用!
核心代碼:
bindService(Intent Service,ServiceConnection conn,int flags)
service:通過該intent指定要啟動的Service
conn:ServiceConnection對象,用戶監(jiān)聽訪問者與Service間的連接情況, 連接成功回調(diào)該對象中的onServiceConnected(ComponentName,IBinder)方法; 如果Service所在的宿主由于異常終止或者其他原因終止,導致Service與訪問者間斷開 連接時調(diào)用
flags:指定綁定時是否自動創(chuàng)建Service(如果Service還未創(chuàng)建), 參數(shù)可以是0(不自動創(chuàng)建),BIND_AUTO_CREATE(自動創(chuàng)建)
//目前安卓版本已經(jīng)不允許通過隱式調(diào)用Service,只能進行顯式調(diào)用
Intent intent1=new Intent(FunctionsActivity.this, ThirdService.class);
bindService(intent1,serviceConnection, Service.BIND_AUTO_CREATE);
-------------------------------------------------------------------------------------------
serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
String tag = ((ThirdService.MyBinder) service).getTag();
Log.d(TAG,tag);
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
這時候回調(diào)函數(shù)的調(diào)用順序是?ThirdService#onCreate ->?ThirdService#onCreate ->?serviceConnection #onServiceConnected。
值得注意的是,onServiceDisconnected這個回調(diào)方法,當你主動調(diào)用unBindService這個方法解綁服務的時候,并不會回調(diào)這個方法。
還有一個Binder的問題,這是一種安卓特有的進程間通信機制,具體的后文會有一個總結(jié)。堅持一下,再看一會就到了。
startService
第二種直接使用startService啟動Service:首次啟動會創(chuàng)建一個Service實例,依次調(diào)用onCreate()和onStartCommand()方法,此時Service 進入運行狀態(tài),如果再次調(diào)用StartService啟動Service,將不會再創(chuàng)建新的Service對象, 系統(tǒng)會直接復用前面創(chuàng)建的Service對象,調(diào)用它的onStartCommand()方法!
但這樣的Service與它的調(diào)用者無必然的聯(lián)系,就是說當調(diào)用者結(jié)束了自己的生命周期, 但是只要不調(diào)用stopService,那么Service還是會繼續(xù)運行的!所以一般在使用這種方式啟動服務的時候,一定要在活動生命周期摧毀的時候進行stopService操作。
//一樣需要顯式調(diào)用
Intent intent2=new Intent(FunctionsActivity.this, ThirdService.class);
startService(intent2);
StartService啟動Service后bindService綁定
其實看這個標題描述就大概知道這個方式在代碼上怎么表現(xiàn)。如果一個Service已經(jīng)通過startService啟動,接著再通過bindService進行綁定,這時候再調(diào)用unbindService解綁,最后再通過bindService綁定,這時候我們就得清晰的知道他的一個回調(diào)函數(shù)的走向了,搞懂這點基本上在流程上就徹底通了。
onCreate( )->onStartCommand( )->onBind( )->onUnbind( )->onRebind( )
這里值得注意的是,在我們學習BindService的時候,了解到當調(diào)用onUnbind的時候,Service會立刻進行onDestory的調(diào)用,但是這里并不會,在這里我們本來一開始進行了startService啟動服務,所以Service就算解綁也不會立刻結(jié)束。
這里另外補充一點,可能大家會覺得第三種啟動方式很雞肋,感覺沒有什么實用的價值。但是轉(zhuǎn)念一想,這些東西如果沒有實用價值怎么可能會被封裝起來呢,對吧。有沒有發(fā)現(xiàn)通過startService方式啟動的service無法直接獲取Binder,無法做到進程間的通信,而通過這種方式,startService也能進行Binder的通信!
Binder
上面一直在說的通信方式Binder到底是什么呢?Binder其實在日常的使用中還是很常見的,所以有必要好好學習一下。
首先我們要知道一個前提條件,進程與進程之間是無法直接通信的。故此Linux系統(tǒng)提供了一種RPC通信模型。RPC模型主要是以一種遷移線程的方式推進。遷移線程允許線程從一個任務“移動”到另外一個任務。在RPC期間,內(nèi)核不會在其IPC(進程間通信)內(nèi)核調(diào)用時阻塞客戶機線程,而是安排他在服務器代碼中繼續(xù)執(zhí)行。
其實上面還是有點生硬解釋,如果你們有學習過Java的后端知識,學習到springcloud的時候,會發(fā)現(xiàn)不同微服務之間明明不同服務器卻能互相調(diào)用服務的方法。這個RPC大概就是這個作用,在兩個本來無法通信獨立的進程之間搭起了一個橋梁,達到通信的作用。
RPC與IPC之間的區(qū)別
相同點:二者之間都可用于進程之間
不同點:RPC強調(diào)的是調(diào)用,一個進程直接調(diào)用另一個進程的方法,而IPC僅僅完成進程之間的互通信,沒有函數(shù)調(diào)用功能。
總結(jié)來說,RPC其實就是添加了進程之間的函數(shù)調(diào)用功能的IPC
Android系統(tǒng)RPC與Binder的關系
Android的RPC并不需要實現(xiàn)不同主機或者不同操作系統(tǒng)間的遠程調(diào)用。跟上面一樣,Andorid的RPC=Binder進程間通信+在Binder基礎上簡歷起來的進程間函數(shù)調(diào)用機制。文章來源:http://www.zghlxwxcb.cn/news/detail-471650.html
對于Binder的使用,上面的代碼事例中還是比較完整,可以劃步到上面仔細看看哦,這邊就不具體說了。文章來源地址http://www.zghlxwxcb.cn/news/detail-471650.html
到了這里,關于安卓四大組件——Service服務(內(nèi)含Binder的簡單解釋)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!