Android四大組件之Service、ContentProvider、BroadcastReceiver

Service

Service 是一個可以在後臺執行長時間運行操作而不提供用戶界面的應用組件。

生命週期

在這裏插入圖片描述
Service的生命週期分啓動服務和綁定服務兩種。

啓動方式(startService)

通過startService啓動服務,stopService停止服務。

生命週期爲onCreate——onStartCommand——onDestroy

存活的時間位於onStartCommand和onDestroy之間

  • onCreate——創建服務時調用,只會調用一次
  • onStartCommand——啓動服務時回調。一旦啓動,服務即可在後臺運行。每次調用startService時都會調用。
  • onDestroy——停止服務時調用。用來清理所有的資源。需要調用stopSelf或stopService停止服務。

綁定方式(bindService)

通過bindService綁定服務和unbindService解綁服務。

生命週期回調順序爲:onCreate——onBind——onUnbind——onDestroy

存活時間爲onBind和onUnbind之間

  • onCreate——創建服務時回調,只會調用一次
  • onBind——綁定服務時回調,綁定服務提供了一個客戶端-服務器接口,允許組件與服務進行交互、發送請求、獲取結果,甚至是利用進程間通信 (IPC) 跨進程執行這些操作,如果不允許綁定,則應返回null。僅當與另一個應用組件綁定時,綁定服務纔會運行。 多個組件可以同時綁定到該服務,但全部取消綁定後,該服務即會被銷燬。只有在第一個客戶端綁定時,系統纔會調用服務的 onBind() 方法來檢索 IBinder,系統隨後無需再次調用 onBind(),便可將同一 IBinder 傳遞至任何其他綁定的客戶端。
  • onUnbind——解綁時回調。當所有客戶端都與Service斷開綁定時調用,默認返回false,當返回值爲true時,後續有新Client綁定時會回調onRebind
  • onRebind——重新綁定時回調。onUnbind返回true,且有新Client綁定時調用。
  • 停止服務時調用——用來清理所有資源。服務與所有客戶端綁定全部取消時,系統會銷燬服務。

在這裏插入圖片描述

IntentService

Service代碼默認運行在主線程,如果做一些耗時操作,會出現ANR的情況。爲了簡單的創建一個異步的、可以自動停止的服務,Android專門提供了一個IntentService類。 只需要實現 onHandleIntent() 方法即可。任務執行完後會自動停止。

關於startService和bindService

使用startService啓動服務後,服務就會啓動,但是這個服務就好像和我們的Activity沒有什麼關係了。

爲了可以和我們的Service進行通信,我們就可以使用bindService方法。

我們可以實現一個繼承自Binder的類,在裏面實現自己想要完成的方法。

然後在Service的onBind方法中返回這個自定義Binder的實例。

在我們的Activity中實現ServiceConnection的實例,在他的onServiceConnection中將Binder向下轉型,然後調用裏面的方法。

這樣就實現了和Service的通信,當Service在其他進程時,Activity和Service則使用Binder進行進程間通信。

AndroidManifest.xml

  • android:name——服務類名
  • android:label——服務的名字,如果此項不設置,那麼默認顯示的服務名則爲類名
  • android:icon——服務的圖標
  • android:permission——申明此服務的權限,這意味着只有提供了該權限的應用才能控制或連接此服務
  • android:process——表示該服務是否運行在另外一個進程,如果設置了此項,那麼將會在包名後面加上這段字符串表示另一進程的名字
  • android:enabled——表示是否能被系統實例化,爲true表示可以,爲false表示不可以,默認爲true
  • android:exported——表示該服務是否能夠被其他應用程序所控制或連接,不設置默認此項爲 false

本地Service和遠程Service

本地服務依附在主進程上,在一定程度上節約了資源。本地服務因爲是在同一進程,因此不需要IPC,也不需要AIDL。相應bindService會方便很多。缺點是主進程被kill後,服務變會終止。

遠程服務是獨立的進程,對應進程名格式爲所在包名加上你指定的android:process字符串。由於是獨立的進程,因此在Activity所在進程被kill的是主進程,該服務依然在運行。缺點是該服務是獨立的進程,會佔用一定資源,並且使用AIDL進行IPC稍微麻煩一點。

startService來說,不管是本地服務還是遠程服務,需要做的工作都一樣。

關於bindService的特點

  • bindService啓動的service和調用者之間是典型的client-server,這裏的調用者是Activity。客戶端是一個或多個。
  • 客戶端可以通過Binder和Service進行通信
  • startService啓動的服務默認無限期執行(調用stopService和stopSelf除外),bindService的生命週期和client息息相關,當client銷燬的時候會自動解綁,也可通過調用解綁的方法進行解綁。當沒有任何綁定的時候,Service會自行銷燬。
  • 回調方法和startService不同。

Content Provider

  • Content Provider是Android系統中爲開發者專門提供的不同應用間進行數據共享的組件。

  • 提供一套標準的接口用來獲取以及操作數據,允許開發者把自己的應用數據根據需求開放給其他應用進行增刪改查。

  • 系統預置了許多Content Provider用於獲取用戶數據,例如聯繫人、日程表等。

在這裏插入圖片描述

設計用意

  • 封裝。對數據進行封裝,提供統一的接口,使用者完全不必關心這些數據是在DB,XML、Preferences或者網絡請求來的。當項目需求要改變數據來源時,使用我們的地方完全不需要修改。
  • 提供一種跨進程數據共享的方式。

數據更新通知機制

數據是在多個應用程序中共享的,當其中一個應用程序改變了這些共享數據的時候,它有責任通知其它應用程序,讓它們知道共享數據被修改了,這樣它們就可以作相應的處理。

ContentResolver接口的notifyChange函數來通知那些註冊了監控特定URI的ContentObserver對象,使得它們可以相應地執行一些處理。ContentObserver可以通過registerContentObserver進行註冊。

ContentProvider的onCreate()是在UI線程運行。


ContentProvider所提供的query(),insert(),delete(),update()都是在ContentProvider進程的線程池中被調用執行的,而不是進程的主線程中。因爲那些方法可能同時被多個線程所調用,所以他們都應該是線程安全的。

Broadcast Receiver

廣播是一種應用間傳輸信息的機制,一個廣播可以有任意個接受者,也可以不被任何應用程序接收。廣播機制是一種典型的發佈-訂閱模式,即觀察者模式。

廣播最大的特點是發送方不需要關心接收方是否接收到這個數據,也不必關心接收方如何處理數據的。通過這種方式來實現接方收方完全解耦。

內部通信使用系統的Binder。

分類

普通廣播

普通廣播是完全異步的,通過 Context 的 sendBroadcast() 函數來發送,消息傳遞的效率比較高,但所有的 receivers(接收器)的執行順序不確定。接收者不能將處理結果傳遞給下一個接收者,並且無法終止廣播 Intent 的傳播,直到沒有與之匹配的廣播接收器爲止。

系統廣播

Android系統中內置了多個系統廣播,只要涉及到手機的基本操作,基本上都會發出相應的系統廣播。如:開機啓動,網絡狀態改變,拍照,屏幕關閉與開啓,電量不足等等。

本地廣播

有的時候我們並不需要把自己的應用內的信息廣播給所有應用,而只是進程內使用,現在使用 Support v4 包中的 LocalBroadcastManager 就能夠實現限於應用內的廣播。

有序廣播

有序廣播通過 Context.sendOrderedBroadcast() 來發送,所以的廣播接收器按照優先級依次執行,廣播接收器的優先級通過 receiver 的 intent-filter 中的 android:priority 屬性來設置,數值越大優先級越高(參數爲 -1000 ~ 1000)。當廣播接收器接收到廣播後,可以使用 setResult() 函數來將結果傳遞給下一個廣播接收器,然後通過 getResult() 函數來取得上一個廣播接收器返回的結果,並可以使用 abortBroadcast() 函數來讓系統丟棄該廣播,使該廣播不再傳遞到別的廣播接收器。

粘性廣播

粘性消息在發送後就一直存在於系統的消息容器裏面,等待對應的處理器去處理,如果暫時沒有處理器處理這個消息則一直在消息容器裏面處於等待狀態,粘性廣播的Receiver如果被銷燬,那麼下次重建時會自動接收到消息數據。

也就是說該廣播會一直保留下去,即使已經有廣播接收器處理了該廣播,當再有匹配的廣播接收器被註冊時,此廣播仍會被接收。如果你只想處理一遍該廣播,可以通過removeStickyBroadcast() 函數實現。

註冊

靜態註冊:即在 AndroidManifest.xml 文件中進行註冊

<receiver
	android:name=".MyBroadcastReceiver"
	android:enabled="true"
	android:exported="true">
	<intent-filter>
		 <action android:name="com.cyy.broad" />
	</intent-filter>
</receiver>

動態註冊:即在代碼中進行註冊

public void registerHelloBroadcast() {
	receiver = new MyBroadcastReceiver();
	registerReceiver(receiver, new IntentFilter("com.cyy.broad"));
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章