淺談 Android服務的使用

服務是一種可以在後臺執行耗時操作任務的不可見的Anroid四大組件之一,它可以IPC(跨進程通信)

爲什麼要有服務,用其他的子線程代替服務不行嗎?

舉個例子,從網絡上下載信息更新的主界面上,4.0以後需要新開線程。如果不用服務,新開一個子線程,如果當前的主線程被系統殺掉或者用戶退出了,子線程就失去控制了。而使用服務就避免了這個問題。

默認情況下,服務運行在主線程中,開啓一個服務有兩種方式:

首先,寫一個類繼承 service 然後 複寫父類的方法

1.startService(這種API建議服務啓動後自生自滅,與調用者沒有任何聯繫)

Activity中通過 startService()方法開啓一個服務,服務類會先執行 onCreate()-->onStartCommand()方法,在onStartCommand()方法中進行相關的操作,例如開啓一個異步任務進行下載操作等等。注意onStartCommand()會返回一個Int類型的值,有以下幾種類型:

1.1 START_NOT_STICKY(非粘性),意思是如果系統殺掉了這個service,那麼系統不會重新去創建一個新的service實例,除非你給它重新發送一個intent去啓動它。

1.2 START_STICKY(粘性),意思是如果系統殺掉了這個service實例,系統會重新創建並啓動service,但是不會傳遞上一個intent,而是傳一個空值

1.3 START_REDELIVER_INTENT,和第二種情況類似,但是會自動傳遞上一個intent

在執行完操作後,可以調用service自身的 stopSelf()或者使用activity中的stopService()方法結束一個服務,然後 service 會自動調用 destory()方法。

2.bindService(這種服務啓動後,可以與調用者進行數據傳遞)

可以在Activity中通過 bindService()綁定一個服務,例如在 activity中的 OnStart()中綁定一個服務,

bindService()方法有三個參數,intent,   serviceConnection對象,服務啓動類型,其中的serviceConn對象需要new 出來,創建時要重寫onServiceConnected() onServiceDisConnected(),其中onServiceConnected()有參數中傳遞一個IBinder類型的對象,這個對象是綁定的service實例啓動時調用 onBind()方法返回的對象,這樣也就實現了綁定類型的service可以回傳數據的功能。

另外,多個組件可以同時綁定一個service,解綁使用unBindService(),當service全部解綁後,調用serviceonDestory()方法結束其生命週期。

因爲service默認運行在主線程中,它不會自動去創建一個子線程,所以,當在service中進行耗時操作的時候,要開啓子線程

另外還有一種service叫做  IntentService ,它是運行在子線程中的,這種比較適合單線程操作(非高併發),它一次只能處理一個線程傳遞過來的操作,只需要複寫它的onHandlerIntent()方法即可

intentService操作流程:

1.開啓子線程去處理從 startCommand()方法中傳遞過來的intent

2.創建工作隊列去維護傳遞過來的intent

3.處理完所有的intent後自動停止服務,不需要你去調用 stopSelf()方法

4.onStartCommand()onBind()都已經在內部寫好,不需要你再重寫了,你只需要重寫 onHandlerIntent()

爲什麼service可以進行IPC

答:綁定的service中有 onBind()方法,這個方法返回一個iBinder接口的實現對象,而在另一端的 ServiceConnection類的創建中有 onServiceConnected()方法,這個方法接收一個iBander對象,而這個對象就是從遠端的 onBind()中返回的。

IBinder接口中有 transact()方法,不要直接使用這個接口,而要通過繼承 Binder類來間接使用,

Transact()有一個參數 Parcel,這個parcel是一個輕量級的遠程通信解決方案的緩衝流,它除了可以通過write寫入數據,通過read讀取數據外,還持有調用它的binder的引用,這樣當一個進程的binder調用 transact()方法時,持有原binder引用去跨進程。調用 transact()方法時,transact()裏面套用了binderonTransact()方法,前一個方法裏面的參數轉移到了後一個方法參數中,當後一個方法處理完後,前一個方法繼續執行並返回結果。這樣保證了事務的原子性。所以在進行這樣的操作的時候,當前的進程是要被堵塞的。

IBinder是遠程IPC調用的一個輕量級的高效的解決方案。

具體做法:

AB傳遞數據,B接到數據處理後回傳給A

1.B中定義一個公共的類繼承Binder,並重寫onTransact()方法,並將這個內部類定義成B的成員變量,在BonBind()方法中返回這個成員變量

2.A中綁定好 service ,拿到從 serviceConnected()返回的參數 binder 對象,在該調用的時候調用 binder.transact()方法,定義一個parcel傳入數據,定義另一個 parcel接收返回的數據,並把他們當做參數傳入 transact()中,然後等待方法執行即可。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章