解析Service之你需要瞭解的一些東東,解析Service之東東

來源:互聯網
上載者:User

解析Service之你需要瞭解的一些東東,解析Service之東東

何為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     @Override12     public void onDestroy() {13         super.onDestroy();14     }15     @Override16     public void onRebind(Intent intent) {17         super.onRebind(intent);18     }19     @Override20     public void onStart(Intent intent, int startId) {21         super.onStart(intent, startId);22     }23     @Override24     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:

//啟動一個ServiceIntent intent = new Intent(this, MyService.class);startService(intent);//停止ServicestopService(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

//綁定一個ServiceIntent intent = new Intent(this, MyService.class);MyServiceConnection conn = new MyServiceConnection();bindService(intent, conn, Context.BIND_AUTO_CREATE);//解除綁定ServiceunbindService(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()。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.