讀古今文學網 > Android程序設計:第2版 > 其他Android組件 >

其他Android組件

Android應用還有一些其他組件,具體包括:Service(服務)、Content Provider(內容提供者)和Broadcast Receiver(廣播接收器)。Service類負責為後台功能提供支持,ContentProvider類是多個應用使用數據存儲的訪問方式,Broadcast Receiver支持多方接收應用所廣播的意圖信息。

組件中還包括Application類,你可能會發現,和組件相比,應用本身是一個相對不重要的單元。設計良好的應用會和Android環境「融為一體」,這些應用可以啟動其他應用的活動,使用它們的功能,通過Android支持組件來提供或增強自身的功能。

意圖和Android應用的標準集對應的常數信息可以在:http://developer.android.com/guide/topics/intents/intents-filters.html和http://developer.android.com/guide/appendix/g-app-intents.html中找到。可以把Android的內容提供者和意圖理解成輔助性API,應該學會使用它們,以便能夠充分利用Android強大的特性並實現和Android平台的無縫集成。

Service

Android的Service類負責為後台執行的任務提供支持,這些任務可能在運行,但是在屏幕上看不到。播放音樂的應用有可能實現成服務,以便在用戶查看網頁時也能夠播放音樂。通過service,應用可以通過長連接來共享一些功能。這種方式在類似FTP和HTTP這樣的Internet服務中是無處不在的,這些服務會一直等待直到客戶端的請求觸發它們。Android平台不會回收服務的資源,所以一旦某個服務啟動了,就很可能可以隨時訪問該服務,除非內存耗盡了。

和Activity類似,Service類提供了控制其生命週期的方法,如停止和重新啟動該服務。

內容提供者

內容提供者(Content Provider)組件和RESTful Web服務非常類似,這些組件也是使用URL,而且ContentProvider子類的操作和RESTful Web操作也很相似,例如發佈和獲取數據。在內容提供者組件中的URI通常是以標識符content://開頭,本地設備可以識別該標識符,使我們能夠訪問內容提供者數據。要使用類ContentProvider,需要指定一個URI及將如何操作引用的數據。以下是內容提供者支持的操作列表,它提供了大家熟悉的四種基本的數據操作:創建(插入)、讀取(查詢)、更新和刪除。

Insert(插入)

類ContentProvider提供的insert方法和REST POST操作類似,作用就是在數據庫中插入新的記錄。

Query(查詢)

類ContentProvider提供的query方法和REST GET操作類似,它返回一組記錄,這些記錄保存在一個特殊的集合類Cursor中。

Update(更新)

類ContentProvider提供的update方法和REST UPDATE操作類似,它用新的記錄更新數據庫中的老記錄。

Delete(刪除)

類ContentProvider提供的delete方法和REST DELETE操作類似,它刪除數據庫中與之匹配的記錄。

注意:REST是「表現層狀態轉換」(Representational State Transfer)的簡稱。它沒有HTTP協議那麼正式,它更多的是一種使用HTTP作為簡單的訪問基礎的概念框架。雖然REST的實現可能有區別,但它們都力爭簡單。Android的內容提供者API把類似於REST的操作作為API正式提供,其設計就是遵循REST的簡單性原則。可以在Wikipedia上得到更多關於REST的信息:http://en.wikipedia.org/wiki/REST。

內容提供者組件是Android內容模型的核心:通過ContentProvider類,應用可以和其他應用共享數據,並管理應用的數據模型。和ContentProvider類密切相關的類ContentResolver,這個類幫助Android系統中的其他組件找到內容提供者。你會發現整個平台有很多內容提供者,它們可以同時用於操作系統和普通應用。值得一提的是,Android應用的核心正是利用內容提供者為新的Android應用提供快速、複雜的功能,包括提供瀏覽器(Browser)、日曆(Calendar)、聯繫方式(Contacts)、呼叫日誌(Call Log)、多媒體(Media)和設置(Settings)等。

內容提供者在進程間通信(InterProcess Communication,IPC)中是獨有的。其不同於在其他平台上構建的一些方式,如CORBA、RMI和DCOM,這些平台重點在於遠程過程調用。內容提供者身兼兩職,既是持久性機制,同時還負責進程間的通信。除了支持進程間的方法調用之外,內容提供者還使得開發人員可以在不同的進程之間高效地共享整個SQL數據庫。除了對象分享,內容提供者還管理著所有的SQL表。

內容提供者的使用

當構建基於服務器的Web應用時,開發人員通常有兩種不同的API訪問方式。首先是構建程序所必須的代碼、庫和數據模型。其次,開發人員還可能調用其他Web應用,使用定義好的API獲取數據和服務。同樣,Android提供也兩級API:一是代碼直接訪問的庫和服務,二是通過內容提供者可用的各種服務。考慮到內容提供者在Android中的重要性,這裡編寫了一個使用內容提供者的簡單客戶端來介紹它。

在這個例子中,使用了最重要的內容提供者之一——Contact數據庫,其應該有助於你去瞭解在應用開發中使用內容提供者的基本方式。類ContentProvider提供了核心的內容提供者API,可以以此為基礎創建一些子類來管理特定類型的數據。Activity使用類ContentResolver及其關聯的URL來訪問特定的內容提供者實例,如下所示:


Cursor c = getContentResolver.query(
      android.provider.ContactsContract.Data.CONTENT_URI,
      new String {
            android.provider.ContactsContract.Data._ID,
            android.provider.ContactsContract.Phone.NUMBER},
      null,
      null,
      null);;
  

Contacts數據庫是在另一個進程中運行的獨立應用。要使用內容提供者,需要調用按照REST風格定義URI的數據操作。內容提供者的URL的形式往往如下所示:


content://authority/path/id
  

其中,authority是Java包內容提供者命名空間(通常就是內容提供者的Java命名空間)。以下是一些內容提供者URI示例:


// references a person
content://contacts/people/25
// this URI designates the phone numbers of the person whose ID is \"25\"
content://contacts/people/25/phones
  

當開發人員調用內容提供者的query方法時,會返回一個Cursor對象,它實現了android.database.Cursor接口對象。通過該接口,可以使用索引每次檢索一條結果(類似於數據庫中的一條記錄),在檢索每一條結果時,索引會自動更新。熟悉JDBC的開發人員可以把android.database.Cursor理解成java.sql.ResultSet。在絕大多數情況下,Cursor對像表示的是在SQLite表上的查詢結果。開發人員可以使用底層SQLite表來訪問cursor的各個字段。下面這個例子的功能就是遍歷Android cursor得到所有字段:


// code from an activity method
Cursor contactsCursor = getContentResolver.query(
    ContactsContract.Contacts.CONTENT_URI,
    null,
    null,
    null,
    null);
if (contactsCursor.moveToFirst) {
   int idx = contactsCursor.getColumnIndex(Contacts.People.DISPLAY_NAME);
   do { name = contactsCursor.getString(idx); }
   while (contactsCursor.moveToNext);
}
  

注意,無論客戶端什麼時候使用provider提供的cursor,當客戶端操作完成後,關閉cursor是至關重要的。如果沒有關閉cursor,會導致嚴重的內存洩露,它會導致應用崩潰。Android提供兩種方式確保在不使用provider cursor時關閉它:

·Activity直接調用Cursor.close方法。

·Activity調用managedQuery方法查詢內容提供者,或調用startManagingCursor(Cursor c)方法。這兩種調用都依賴於系統來檢查cursor的引用,判斷給定的引用是否已經沒有活躍的客戶端。當引用計數顯示所有的客戶端已經結束操作時,系統本身會調用Cursor.close方法。

我們將在第12章和第13章更詳細地介紹數據和內容提供者。

內容提供者和互聯網

內容提供者和Android應用中的Activity組件一起構成了「模型-視圖-控制器」(Model-View-Controller,MVC)架構的必要組成部分。除了支持REST風格的操作外,它們還支持MVC的觀察者模式(observer pattern)。類ContentResolver提供notifyChange方法,向使用registerContentObserver方法註冊了content observer的Cursor對像廣播數據庫中的變化。

也許你會想:「好吧,但是我所感興趣的數據是在互聯網上。」Android提供了很多可以訪問這些數據的工具。你很可能已經使用過某些應用,它們直接使用了Android的網絡類來訪問互聯網上的數據。遺憾的是,你往往可以識別出這些應用,因為它們需要很長時間來訪問和檢索數據,甚至會在你等待過程中顯示進度標示。

如果能夠增強內容提供者的功能,使它能夠在本地緩存數據,此外,Android以數據庫為中心的MVC架構本身也支持在有新數據到達時再在用戶屏幕上顯示,這樣豈不是更好?第13章將會介紹這種方式。第13章將介紹在Android中如何結合用戶接口、內容提供者及其相關的類、Android的網絡API及MVC支持來創建REST客戶端,該客戶端會利用內容提供者架構和REST的相似性,使得在應用獲取數據的過程中,不需要用戶一直盯著進度條。

BroadcastReceiver

BroadcastReceiver(廣播接收器)類通過Intent對像實現了另一種Android高層進程間的通信機制。BroadcastReceiver的生命週期比已經介紹過的其他組件的生命週期更簡單。和活動類似,廣播接收器也是接收Intent對象的處理,不同的是它有自己的用戶界面。廣播接收器的典型使用方式是接收告警,在特定時間激活應用。