android Content Provider詳解一

Content providers管理對結構化數據集的使用.它們封裝數據,並提供瞭數據安全的機制.Content providers是從一個進程連接另一個進程中的數據的標準接口.

當你想使用一個content provider中的數據,你需在你的應用的Context 中使用ContentResolver對象作為客戶端與provider 進行通訊.ContentResolver對象與provider對象通訊,provider是實現ContentProvider的類.Provider對象接收客戶端發來的請求,執行請求的動作,返回結果.

如果你不想把你的數據共享給其它應用,你不需開發你自己的provider.然而,你需要自己的provider來在你的應用中提供自定義搜索建議.如果你需要從你的應用中考貝復雜的數據或文件粘貼到其它應用中,你也需要提供自己的provider.

Android自己包含瞭管理音頻,視頻,圖像,個人通訊錄等數據的content providers.你可以從android.provider 包的參考文檔中爪到它們.這些providers 可以被所有的android應用使用,但可能帶有一些限制.

Content Provider 基礎
一個content provider 管理對中央數據倉庫的使用.一個provider是一個Android應用的一部分,應用一般提供它自己的UI來操作數據.然而,content providers主要是為瞭給其它應用使用,其它的應用使用provider客戶端對象來操作provider.providers 和provider客戶端一起提供瞭一致的,標準的接口來操作用於進程間通訊的數據並保處數據的安全性.

本節講解以下基礎知識:

· content providers如何工作.

· 從content provider取得數據的API.

· 向content provider插入,更新以及刪除數據的API.

· 其它有助於使用providers的API.

概述
一個content provider代表瞭面向外部應用的數據,這些數據看起來就像關系型數據庫中的一個或多個table.一行代表某種數據類型的一個實例,一列代表這個實例的一個屬性或字段.

舉個例子,Android平臺中的一個內建的provider是用戶詞典,它存儲瞭用戶想保存的非標準詞的拼寫.表1 演示瞭數據在provider的表中可能看起來的樣子:

Table 1: 簡單用戶詞典表

word
 app id
 frequency
 locale
 _ID
 
mapreduce
 user1
 100
 en_US
 1
 
precompiler
 user14
 200
 fr_FR
 2
 
applet
 user2
 225
 fr_CA
 3
 
const
 user1
 255
 pt_BR
 4
 
int
 user5
 100
 en_UK
 5
 

在上表中,每行代表瞭一個不能在標準字典中找到的詞.每一列代表瞭這個詞瞭一個屬性.列頭是存儲在provider中的列的名字.要引用一行的locale屬性,需引用locale 列.對於這個provider,_ID列作為"主鍵"列,provider會自動管理它.

註:一個provider不是必須具備主鍵的,並且也不是必須使用_ID 作為主鍵的列名來引用一行.然而,如果你把一個provider綁定到一個ListView,就必須有一個列名叫做_ID.此需求將在顯示查詢結果一節中有詳細的解釋.

操作一個provider
應用使用ContentResolver客戶端對象來操作content provider中的數據.此對象具有一些與provider 對象中同名的方法,provider對象指的是某個ContentProvider具體派生類的實例.ContentResolver 的方法們提供瞭對存儲數據的基本的"CRUD" (增刪改查)功能.

ContentResolver 對象處於客戶端應用的線程中,ContentProvider 對象位於另外的進程並且自動處理進程間通訊. ContentProvider 也代表瞭數據層與可視層之間的一個抽象層.

註:要使用一個provider,你的應用通常需要在manifest請求一些權限, 這將在Content Provider 權限一節中進行更詳細的講解.

舉個例子,要從用戶詞典Provider中獲取取單詞和它們的locale列表,你需調用ContentResolver.query().query() 方法會調用用戶詞典中的ContentProvider.query() 方法.下面的代碼演示瞭ContentResolver.query() 調用:

// 查詢用戶詞典並返回結果
mCursor = getContentResolver().query(
    UserDictionary.Words.CONTENT_URI,   // 單詞表的content URI
    mProjection,                        // 每行要返回的列們
    mSelectionClause                    // Selection的條件
    mSelectionArgs,                     // Selection的條件
    mSortOrder);                        // 返回各行要如何排序

表2展示瞭query(Uri,projection,selection,selectionArgs,sortOrder) 的參數們如何與一個SQL SELECT語句匹配:

Table 2: Query() 與SQL 查詢的對比

query() argument
 SELECT keyword/parameter
 Notes
 
Uri
 FROM table_name
 Uri 對應provider 中叫做table_name的表.
 
projection
 col,col,col,…
 projection 是每行要包含的列們
 
selection
 WHERE col = value
 selection 指定瞭一些選擇條件
 
selectionArgs
 (不能對應.替換selection參數各類似於? 的占位符)
 
sortOrder
 ORDER BY col,col,…
 sortOrder 指定排序方式
 

 

Content URIs
content URI 是一個標志provider中的數據的URI.Content URI中包含瞭整個provider的以符號表示的名字(它的authority) 和指向一個表的名字(一個路徑).當你調用一個客戶端的方法來操作一個provider中的一個表,指向表的content URI是參數之一.

常量CONTENT_URI 中包含瞭用戶詞典table的content URI.ContentResolver 對象分析出URI的authority,並使用它與一個已知provider組成的系統表中的authority進行對比來"解決"provider.ContentResolver之後就會派送查詢參數給正確的 provider.

ContentProvider使要長content URI的路徑辨別分來選擇要操作的表.通常一個provider中要暴露的每個表都具有一個路徑.

在上面的例子的代碼中,"詞典"表的全URI是:

content://user_dictionary/words

user_dictionary部分是provider的 authority,words部分是表的路徑.字符串 content:// (the scheme) 總是要存在,它表示引用一個content URI.

很多provider允許你通過在URI的末尾增加一個ID來操作表中一個單獨的行.例如,要從用戶詞典中獲取_ID是4的一行,你可要行使用這樣的content URI:www.aiwalls.com

Uri singleUri = ContentUri.withAppendedId(UserDictionary.Words.CONTENT_URI,4);

當你要獲取多行然後更新或刪除其中一時,你經常要使用的是id值.

註:Uri和Uri.Builder類包含由字符串構建格式正確的Uri對象的簡便的方法們.ContentUris 包含向一個URI添加id值的簡便方法們.上面的小代碼片段就是使用瞭withAppendedId() 來向UserDictionary content URI添加id.

 

作者:nkmnkm

發佈留言