Content Providers

轉:http://www.cnblogs.com/tekkaman/archive/2011/06/09/2075626.htmlhtml

Content Providersandroid

  Content Providers存儲和取得數據,以及讓它對全部應用程序可見。這是唯一的跨應用程序共享數據的方法;沒有一個全部Android包都能訪問的公共存儲區域。數據庫

  Android整理了一大堆content provider給公共數據類型(音頻、視頻、圖像、聯繫人信息等待)。你能看見他們中的一些在android.provider包中。你能查詢providers擁有的數據(雖然,有一些,你必須獲取合適的權限來讀取數據)。數組

  若是你但願作你本身的數公共數據,你有兩個選項:你能夠建立你本身的content provider(一個ContentProvider子類)或你能夠添加數據到一個已存在的provider--若是有一個控制一樣的數據類型的話而且你擁有寫的權限。ide

Content Provider Basicsspa

  一個content provider怎樣實際存儲它的數據由設計者決定。但全部的content provider實現一個公共的接口來查詢和取得結果--一樣的對添加、修改、刪除數據。設計

  這是一個客戶間接使用的接口,通常經過ContentResolver對象。你獲取一個ContentResolver經過getContentResolver()從activity的實現或其它組件:3d

  

  你能夠而後使用ContentResolver的方法來和你感興趣的任何content provider交互。orm

  當一個查詢被初始化,android系統標識被找準的content provider,保證它在運行。系統立馬示例全部的ContentProvider對象;你永遠不須要本身來作。實際上,你永遠不會直接處理ContentProvider。典型的,每一個ContentProvider只有一個實例。但它能夠和多個ContentResolver對象交互在不一樣的應用程序和不一樣的進程 。進程間交互被ContentResolver和ContentProvider操做。視頻

The data model

  Content providers暴露他們的數據做爲簡單的表在基於一個數據庫模型,每行是一條記錄,每一列是特定類型的數據。例如,關於人的信息和他們的手機能夠暴露以下:

  每一條記錄包含一個數字_ID域用來唯一標識記錄在表中。IDs能夠被用來匹配記錄在相關表中--例如,爲了找到一我的的電話號碼在一個表以及在另外一個表中的圖。

  查詢返回一個Cursor對象,能夠移動從記錄到記錄而且列到列來讀取每一個域的內容。它有特殊的方法來讀取每一個類型的數據。因此,爲了讀一個域,你必須知道哪一種類型的數據這個域包含。

URIs

  每個content provider暴露一個公共的URI(Uri對象),用來識別數據集。一個content provider控制多個數據集(多個數據表)爲每一個暴露一個URI。全部的URIs以"content://"開始。"content:"方案標識數據被content provider控制。

  若是你定義一個content provider,定義一個常量爲它的URI是個好主意,爲了簡化客戶端代碼而且讓之後升級更乾淨。Android定義CONTENT_URI常量爲全部的平臺providers。例如,一個表的URI匹配某我的的電話而且這個表的URI擁有這我的的圖片(都被聯繫人content provider控制):

  

  URI常量被用於content provider的交互。每一個ContentResolver方法以URI做爲第一個參數。它標緻着哪一個一providerContentresolver須要去交流而且哪個表須要被指向。

Querying a Content Provider

  你須要三種信息來查詢一個content provider:

  一、標識provider的URI。

  二、你但願接收的域名。

  三、這個域的數據類型。

  若是你查詢某一個記錄,你也須要那條記錄的ID。

Making the query

  爲了查詢一個content provider,你可使用ContentResolver.query()方法或Activity.managedQuery()方法。兩個方法使用相同的參數,兩個都返回Cursor對象。但是,managedQuery()引發activity來管理 Cursor的生命週期。一個被管理的Cursor操做全部的細節,例如卸載它本身當activity中止,查詢它本身當activity重啓。你能夠要求一個Activity去管理一個未被管理的Cursor對象爲你,經過Activity.startManagingCursor()。

  第一個給query()或managedQuery()的參數是provider的URI--自助CONTENT_URI常量標識一個特定的ContentProvider和數據集。

  爲了限制一個查詢只能一條記錄,你能夠添加_ID值給給那個URI--也就是說,放一直匹配的字符串到URI的最後的部分。例如,若是ID是23,那麼 URI就會是:

  

  有一些幫助方法,特別是ContentUris.withAppendedId()和Uri.withAppendedPath(),使得添加一個ID到URI很容易。兩個靜態方法都返回一個添加了ID的Uri對象。因此,例如,若是你在尋找23號記錄在聯繫人數據庫中,你能夠構造一個查詢像下面這樣:

  

  其它參數限制query()和managedQuery()方法到更細節。他們是:

  一、返回的數據列的名字。NULL值返回全部列。不然,只有被列出名字的值纔會返回。全部和平臺一塊兒的content providers定義常量爲他們本身列。例如,android.provider.Contacts.Phones類定義 常量爲列名在phone表中就像以前陳述的&mdash _ID、NUMBER、NUMBER_KEY、NAME等等。

  二、一個跟行有關的過濾器,以SQL WHRER每每名(不包含WHERE itself)。一個NULL值返回全部行(除非URI限制單選查詢)。

  三、選擇參數。

  四、一個排序的行被返回,格式化像SQL ORDER從句(不包括ORDER BY itself)。一個NULL值返回原始記錄順序,也就是沒有排序。

   讓咱們看一個查詢示例,取得聯繫人名字和他們電話號碼的列表:

  這個查詢從聯繫人content provider的人員表中取得數據。它取得名字,電話號碼,和唯一的記錄ID。它也報告記錄的數量做爲被每條記錄的_COUNT返回的。

  列名常量被定義在不一樣的接口--_ID和_COUNT在BaseColumns,NAME在PeopleColumns,以及NUMBER在phoneColumns。Contacts.People類實現每一個接口。

What a query returns

  一個查詢返回一系列的零或更多數據庫記錄。列表、默認序、數據類型對每一個content provider來講都很特別。但每個provider 有一個_ID列。每一個provider也能將記錄數返回在_COUNT列中;它的值和全部的行同樣。

  下面是一個例子,展示以前的結果:

  

  取得的數據被暴露給一個Cursor對象能夠向後或向前穿越結果集。你可使用這個對象只讀數據。添加、修改、刪除數據,你必須使用一個ContentResolver對象。

Reading retrieved data

  經過查詢得到的Cursor提供訪問結果記錄的功能。若是你已經查詢一個特定記錄經過ID,這個集合將包含只有一個值。不然,它能夠包含多個值。(若是沒有匹配,它爲空)你能夠讀取數據從指定域在記錄中,但你必須知道域的數據類型,由於Cursor對象有一個單獨的方法來讀各類類型的數據--例如getString(),getInt()和getFloat()。(但是,對大多數類型,若是你調用 讀取字符串的方法,Cursor對象將給你數據的字符串表示。)Cursor讓你請求表列名用索引號,或用列名獲取索引號。

  下面的版本陳述讀取名字和電話號碼從以前的查詢:

  

  若是一個查詢能返回二進制數據,例如圖形或聲音,數據 能夠直接進入表或數據的表頭多是一個字符串「content:URI」,你能使用來獲取數據。通常,比較小的數據(20-50K或更小)常常被直接插入表中並表能夠被Cursor.getBlob()讀取。它返回一個二進制數組。

  若是表入口是「content:URI」,你應該永遠不嘗試打開和讀取文件直接(其中一點是,權限會致使失敗)。相反,你應該調用ContentResolver.openInputStream()來獲取一個InputStream對象,你能夠用來讀取數據。

Modifying Data

  被content provider保存的數據能夠被修改:

  一、添加一條新記錄。

  二、添加新值到當前的記錄。

  三、批量更新當前記錄。

  四、刪除記錄。

  全部的數據修改都經過ContentResolver完成。一些content provider要求更嚴格的權限寫數據。若是你沒有權限寫入一個content provider,ContentResolver會失敗。

Adding records

  添加一條新記錄給一個content provider,首先創建鍵-值對在ContentValues對象,每一個key匹配列名在content provider,而且值是那個記錄的那個列指望的值。而後調用ContentResolver.insert()而且傳遞它provider的URI和ContentValues 地圖。這個方法返回完成的新記錄的URI--也就是,provider的新記錄添加了ID的URI。你可使用這個URI來查詢和得到Cursor關於這條新記錄的,而且進一步修改數據。下面是一個例子:

  

Adding new values

  一旦記錄創建,你能夠添加新信息爲它或修改已存在的信息。例如 ,下一步在上例中將添加聯繫人信息--像電話號碼或IM或e-mail地址--給新的入口。

  最好的方式添加一條記錄在聯繫人數據庫是添加表的名字在URI後面,而後使用這個改動的URI來添加數據值。每一個聯繫表導出一個名字爲這個目錄做爲CONTENT_DIRECTORY常量。下面的代碼繼續以前的示例經過添加一個電話號碼和郵件地址給新記錄:

  

  你能夠放置小量二進制數據到表中經過調用ContentValue.put()。它對像小圖標或短音頻起做用,例如。但是,若是你有一大量二進制數據來添加,例如一個圖片或一首完整歌曲,爲數據放置"content:URI"在表中而且調用ContentResolver.openOutputStream()用文件的URI。(這引發content provider存在數據在一個文件,而後記錄文件地址在一個隱藏域。)

  在這點上,MediaStore content provider,這個主要的分發圖像、音頻、視頻的provider,利用一個特別的協議:一樣的使用query()和managedQuery()的URI來獲取meta-information關於二進制數據(例如,圖像的標題或拍攝的日期)和openInputStream一塊兒使用來獲取它自身的數據。相似的,和insert()使用的URI放置meta-information給一個MediaStore和openOutputStream的記錄來旋轉二進制數據那裏。下面的代碼版本陳述了這個協議。

  

Batch updating records

  爲了氣量更新一組記錄(例如,爲了改變「NY」成「New York」在全部的域),調用ContentResolver.update()方法用列和值來改變。

Deleting a record

  爲了刪除單條記錄,調用 ContentResolver.delete()用URI和指定的行。

  爲了刪除多條記錄,調用 ContentResolver.delete()用記錄類型的URI和來刪除(例如,android.provider.Contacts.Peopple.CONTENT_URI)而且一個SQL WHERE從句有寫哪行被刪除。(警告:保證包含一個有效的WHERE若是你在刪除通常類型,不然你將有刪除比你但願的更多的數據)。

相關文章
相關標籤/搜索