編輯:關於android開發
何為Service
Service,俗名服務。在Android系統中,Service與Activity就像一個媽生的,不僅長得像,而且行為(生命周期)也有一些類似。對於Activity來說大家肯定不會陌生,開發Android應用中打過交道最多的莫非就是Activity了,所以今天我們借助Activity來引入講解Service。Service跟Activity一樣是Android的四大組件之一,需要在AndroidManifest清單文件中進行注冊。Service不像Activity在前台運行,而且是與之呼應進行後台運行的服務;如果把Activity當成下載軟件的用戶交互界面,而Service就是那個默默在後台運行的下載線程,所以Service的應用場景就是那些我們不需要它常駐前台但需要它一直在後台工作的時候,例如下載、播放音樂、IM軟件監聽客戶端消息等。
Service的啟動
啟動Service有兩種方式,不單調且奢華。在組件中我們可以用類似於Activity的啟動方式的startService()來啟動Service,用stopService()來關閉啟動的服務;當然也可以用比較獨特的綁定啟動方式bindService()來啟動Service這個服務,對應的解綁方法自然就是unbindService()。當然這兩種啟動方式的不同也意味著Service有著不一樣的生命周期調用方法,我們先來看看Service啟動的代碼,詳細如下:
定義一個Service類:
1 public class MyService extends Service { 2 //onBind為必須實現的抽象方法 3 @Override 4 public IBinder onBind(Intent arg0) { 5 return new MyBinder(); 6 } 7 @Override 8 public void onCreate() { 9 super.onCreate(); 10 } 11 @Override 12 public void onDestroy() { 13 super.onDestroy(); 14 } 15 @Override 16 public void onRebind(Intent intent) { 17 super.onRebind(intent); 18 } 19 @Override 20 public void onStart(Intent intent, int startId) { 21 super.onStart(intent, startId); 22 } 23 @Override 24 public boolean onUnbind(Intent intent) { 25 return super.onUnbind(intent); 26 } 27 /** 28 * 構造一個MyBinder類,其繼承於Binder,而Binder實現了IBinder的接口 29 */ 30 public class MyBinder extends Binder{ 31 //返回Service實例的引用 32 public MyService getId(){ 33 return MyService.this; 34 } 35 } 36 }
啟動方式為startService:
//啟動一個Service Intent intent = new Intent(this, MyService.class); startService(intent); //停止Service stopService(intent);
startService()啟動方式的生命周期為:
context.startService() -> onCreate() -> onStart() -> Service 運行中 -> context.stop() -> onDestroy() -> Service 被關閉
啟動方式為bindService:
需要先構造一個實現ServiceConnection接口的一個連接類
1 private class MyServiceConnection implements ServiceConnection{ 2 public MyServiceConnection(){} 3 @Override 4 public void onServiceConnected(ComponentName arg0, IBinder binder) { 5 MyService Myservice = ((MyService.MyBinder)binder).getService(); 6 //綁定成功後調用 7 } 8 @Override 9 public void onServiceDisconnected(ComponentName arg0) { 10 //當服務奔潰時調用 11 } 12 }
然後進行綁定啟動Service
//綁定一個Service Intent intent = new Intent(this, MyService.class); MyServiceConnection conn = new MyServiceConnection(); bindService(intent, conn, Context.BIND_AUTO_CREATE); //解綁Service unbindService(conn);
當我們執行bindService()後,系統將會調用onCreate()和onBinde(),而在onBind()執行完畢後,將會回調ServiceConnection中的onServiceConnected()的方法,同時傳回一個實現了IBinder接口的類(一般會選擇傳回繼承至Binder的子類,因為Binder實現了IBinder的接口),然後我們可以通過某些手段(參考上面代碼)從IBinder中獲取Service的實例,一旦拿到了引用就相當於拿到了控制權,那時你要怎麼玩弄Service還不是你自家兒的事情了。。。
bindService()啟動方式生命周期:
context.bindService() -> onCreate() -> onBind() -> Service 運行中 -> context.unBindService() -> onUnbind() -> onDestroy() -> Service被關閉
以上兩條生命周期非常正規的執行流程,但是哲學觀告訴我們,有普遍就有特例,所以有一些奇葩的生命流程的存在也是可能的。
情形一:當我們在組件中調用startService()了來啟動Service,但是我們並沒有調用stopService()來銷毀這個服務,那麼我們在再次startService()來啟動這個服務的時候,並沒有調用onCreate()這個回調方法,而是僅僅執行了onStart()。為什麼呢?因為在Android系統,每個服務都被設置成單例模式,無論調用多少次startService()來啟動Service,在系統永遠只會運行一個Service。而onCreate()是Service被創建時被調用的,所以在多次重復啟動Service不會調用onCreate(),因為此時系統中已經存在Service這個服務了,所以只會調用onStart()。也就是說在多次啟動服務時,onCreate()只會被調用一次,而onStart()可以被調用多次。
情形二:當我們需要把通過startService()啟動的Service掃地出門的時候,調用stopService()就能滿足我們小小的要求,這時候程序一般如我們預料的執行onDestroy()。但是如果我們並沒有祭出stopService()這把寶劍,而是把調用者(如Activity)直接kill掉,那麼會執行onDestroy()這個方法嗎?答案是不會的,因為自從啟動了Service後,該服務就跟調用者撇清關系了,不論調用者生老病死都跟他沒半毛錢關系,除非打出stopService()通過意圖(intent)把服務回收,當然這一切是建立在該Service是通過startService的方式啟動的前提上。
情形三:現在說一下綁定服務(bindService)的情況,同startService的方式一樣,如果多次重復啟動Service,onCreate()依然只會調用創建Service服務的那個第一次。而對於onBind()則會在每次重復綁定服務的時候被調用,請示在這裡onBind()最主要的作用就是將Ibinder傳回到綁定者,借用其建立綁定者與Service的聯系。而如果有多個綁定的存在,那麼執行unbindService()僅僅只會觸發onUnbind()而不會觸發onDestroy(),只有最後一個綁定者調用unbindService()才會觸發服務的onDestroy()的調用。還有一個特別的地方就是,如果銷毀綁定者(例如Activity),那麼綁定的這個Service會隨他而去(執行onUnbid->onDestroy)。
關於Service的一些小知識小技巧
1、如果你需要一個在調用者退出後仍然不會被銷毀,但同時需要獲取他的引用,那麼有這麼一個小方法。先startService()啟動服務,然後bindService綁定該服務,此時可以獲取到Service的引用,然後在解綁unbindService,由於先startService所以只會執行onUnbind(),這時由於沒有綁定關系,就算該調用者掛掉了,Service依然運行如舊。
2、Service雖然說是後台運行,但是實際上說它仍然是運行在主線程,這裡說得運行在主線程是其onCreate、onStart、onBind等生命周期方法運行在主線程,如果這些方法進行諸如下載、讀取大文件等耗時工作,會引起主線程的阻塞;所以我們一般會在Service中另起子線程運行我們需要的業務。
3、Service的啟動、綁定和停止、解綁應該在對應的調用者相應的生命周期中,例如需要Service貫穿整個Activity,我們可以再onCreate中啟動、綁定Service、在onDestroy中停止或解綁Service。如果只是需要在用戶前台時運行服務,那麼應該在onStart和onStop中進行相應的處理。不建議在onPause和onResume中對於服務進行啟動停止的操作,因為這樣會可能造成不必要的性能消耗,舉個例子,當兩個activity同時需要這個服務,那麼在前個activity的onPause剛結束服務時,下個activity在onResume馬上啟動該服務,造成一些惡心的問題。
4、有人認為為什麼在bindService的時候不把Ibinder返回到調用者那裡,這個是因為啟動服務時異步的,在調用bindService的時候是無法獲取IBinder並返回的,所以只能在後面通過調用onbind的時候把IBinder扔到onServiceConnected的參數裡面。
5、有些人會碰到onServiceConnected()在bindService後並沒有被調用,請檢查你的onBind()函數,如果返回值為null是不會觸發onServiceConnected()的回調的,所以我們要確保onBind返回的是一個實現了IBinder接口的類。
6、我們可以在onUnbind()方法中返回true,這樣的話,在我們解綁Service後再次綁定該Service,將會調用onRebind()這個不怎麼常見的回調方法,而不會去執行onBind()。
ELF Format 筆記(十三)—— 段權限,elfformatilocker:關注 Android 安全(新手) QQ: 2597294287 一個可被系統加載的程序
A DB2 Performance Tuning Roadmap --LOG INTRODUCTION本文的內容是在整理報表時,對DB2 STAT LOG AVITIVI
轉載 Android 多線程處理之多線程用法大集合,android大集合handler.post(r)其實這樣並不會新起線程,只是執行的runnable裡的run()方
高仿人人網客戶端安卓源碼,高仿人人安卓源碼 高仿人人網客戶端,有興趣的盆友可以研究下,裡面主要包含的一些UI設計與交互。(注:項目中有少許問題,apk