Android中程式與Service互動的方式——綜述

lostinai發表於2013-06-03

  http://blog.csdn.net/yihongyuelan/article/details/7215990

      本文將通過三大部分來講解Android中程式與Service的互動方式,這裡說的互動方式指的是如何與Service進行訊息的傳遞,比如:從Service中獲取資訊,向Service傳送資訊等等。舉個簡單的例子,當我們通過手中的Android裝置在網路上下載電影的時候,我們需要使用Service實現在後臺下載,但同時將下載進度通過當前的Activity來展示給使用者,那麼我們就需要和Service有一個實時互動的動作。

      文章分為:綜述、五種互動方式的講解、總結這三部分。在第二部分中列出了五種互動方式,分別是:通過廣播互動、通過共享檔案互動、通過Messenger(信使)互動、通過自定義介面互動、通過AIDL互動。

      什麼是Service?

      Service翻譯過來就是服務的意思,當我們的應用程式需要做一個長耗時的操作,還有可能需要和別的程式互動的時候,我們就需要使用Service。

      1.    Service不是一個單獨的程式,除非單獨宣告,否則它不會執行在單獨的程式中,而是和啟動它的程式執行在同一個程式中。

      2.    Service不是執行緒,這意味著它將在主執行緒裡執行。

     也就是說Service既不是程式也不是執行緒,它們之間的關係如下:


      可能有的朋友會問了,既然是長耗時的操作,那麼Thread也可以完成啊。沒錯,在程式裡面很多耗時工作我們也可以通過Thread來完成,那麼還需要Service幹嘛呢。接下來就為大家解釋以下Service和Thread的區別。

      首先要說明的是,程式是系統最小資源分配單位,而執行緒是則是最小的執行單位,執行緒需要的資源通過它所在的程式獲取。

      Service與Thread的區別:

      Thread:Thread 是程式執行的最小單元,可以用 Thread 來執行一些非同步的操作。

      Service:Service 是android的一種機制,當它執行的時候如果是Local Service,那麼對應的 Service 是執行在主程式的 main 執行緒上的。如果是Remote Service,那麼對應的 Service 則是執行在獨立程式的 main 執行緒上。

      Thread 的執行是獨立的,也就是說當一個 Activity 被 finish 之後,如果沒有主動停止 Thread 或者 Thread 裡的 run 方法沒有執行完畢的話,Thread 也會一直執行。因此這裡會出現一個問題:當 Activity 被 finish 之後,不再持有該 Thread 的引用,也就是不能再控制該Thread。另一方面,沒有辦法在不同的 Activity 中對同一 Thread 進行控制。
      例如:如果 一個Thread 需要每隔一段時間連線伺服器校驗資料,該Thread需要在後臺一直執行。這時候如果建立該Thread的Activity被結束了而該Thread沒有停止,那麼將沒有辦法再控制該Thread,除非kill掉該程式的程式。這時候如果建立並啟動一個 Service ,在 Service 裡面建立、執行並控制該 Thread,這樣便解決了該問題(因為任何 Activity 都可以控制同一個Service,而系統也只會建立一個對應 Service 的例項)。
      因此可以把 Service 想象成一種訊息服務,可以在任何有 Context 的地方呼叫 Context.startService、Context.stopService、Context.bindService、Context.unbindService來控制它,也可以在 Service 裡註冊 BroadcastReceiver,通過傳送 broadcast 來達到控制的目的,這些都是 Thread 做不到的。

      啟動service有兩種方法:
      1.    Context.startService()
             呼叫者(Client)與服務端(Server)之間沒有關聯,即使呼叫者退出,服務仍可執行。
      2.    Context.bindService()
             呼叫者(Client)與服務端(Server)繫結在一起,可以多個呼叫者(Client)繫結一個服務端(Server),當所有的呼叫者(Client)退出,服務端(Server)也就終止。

      Service的生命週期:

      1.    被啟動的服務(startService())的生命週期。
             如果一個Service被某個Activity 呼叫Context.startService() 方法啟動,那麼不管是否有Activity使用bindService()繫結或unbindService()解除繫結到該Service,該Service都在後臺執行。如果一個Service被多次執行startService(),它的onCreate()方法只會呼叫一次,也就是說該Service只會建立一個例項,而它的onStartCommand()將會被呼叫多次(對應呼叫startService()的次數)。該Service將會一直在後臺執行,直到被呼叫stopService(),或自身的stopSelf方法。當然如果系統資源不足,系統也可能結束服務。
      2.    被繫結的服務(bindService())的生命週期。
             如果一個Service被呼叫 Context.bindService ()方法繫結啟動,不管呼叫bindService()呼叫幾次,onCreate()方法都只會呼叫一次,而onStartCommand()方法始終不會被呼叫,這時會呼叫onBind()方法。當連線建立之後,Service將會一直執行,除非呼叫Context.unbindService() 斷開連線或者之前呼叫bindService() 的 Context 不存在了(如該Activity被finish),系統將會自動停止Service,對應onDestroy()將被呼叫。
      3.    被啟動又被繫結的服務的生命週期。
             如果一個Service又被啟動又被繫結,則該Service將會一直在後臺執行。呼叫unbindService()將不會停止Service,而必須呼叫stopService()或Service的stopSelf()方法來停止服務。
      4.   當服務被停止時清除服務。
            當一個Service被終止時,Service的onDestroy()方法將會被呼叫,在這裡應當做一些清除工作,如停止在Service中建立並執行的執行緒等。

      Process的生命週期:

      當Service執行在低記憶體的環境時,系統會kill掉一些程式。因此程式的優先順序將會狠重要:
      1.    如果Service當前正在執行onCreate()、onStartCommand()、onDestroy()方法,那麼此時主程式將會成為前臺程式來保證程式碼可以執行完成而避免被kill。
      2.    如果Service已經啟動,那麼主程式將會比其他可見的程式的重要性低,但比其他看不見的程式高。這裡說的可見指的是對使用者來講,可見的程式優先順序永遠是最高的,使用者至上嘛。但只有少部分程式始終是使用者可見的,因此除非系統處於極度低記憶體的時候,不然 service是不會被kill的。
      3.    如果有Client端連到Service,那麼Service永遠比Client端重要。
      4.    Service可以使用startForeground()將Service放到前臺狀態。這樣在低記憶體時被kill的機率更低,但如果在極低記憶體的情況下,該Service理論上還是會被kill掉。但這個情況基本不用考慮。

      以上文章將要涉及到的知識進行了初步講解,包括Service的基礎知識以及為什麼要用Service,後續文章將探討與Service互動的幾種方式。

相關文章