Android是如何?應用程式之間資料共用的。一個應用程式可以將自己的資料完全暴露出去,外界更本看不到,也不用看到這個應用程式暴露的資料是如何 儲存的,或者是使用資料庫還是使用檔案,還是通過網上獲得,這些一切都不重要,重要的是外界可以通過這一套標準及統一的 介面和這個程式裡的資料打交道,例如:添加(insert)、刪除(delete)、查詢(query)、修改(update),當然需要一定的許可權才可以。
如何將應用程式的資料暴露出去。 Android提供了ContentProvider,一個程式可以通過實現一個Content provider的抽象介面將自己的資料完全暴露出去,而且Content providers是以類似資料庫中表的方式將資料暴露。Content providers儲存和檢索資料,通過它可以讓所有的應用程式訪問到,這也是應用程式之間唯一共用資料的方法。要想使應用程式的資料公開化,可通過2種方法:建立一個屬於你自己的Content provider或者將你的資料添加到一個已經存在的Content provider中,前提是有相同資料類型並且有寫入Content provider的許可權。
如何通過一套標準及統一的介面擷取其他應用程式暴露的資料。Android提供了 ContentResolver,外界的程式可以通過ContentResolver介面訪問ContentProvider提供的資料。
當前篇主要說明,如何擷取其它應用程式共用的資料,比如擷取Android 手機電話薄中的資訊。
什麼是URI。
在學習如何擷取ContentResolver前,有個名詞是必須瞭解的:URI。URI是網路資源的定義,在Android中賦予其更廣闊的含義。
將其分為A,B,C,D 4個部分:
A:標準首碼,用來說明一個Content Provider控制這些資料,無法改變的;
B:URI的標識,它定義了是哪個Content Provider提供這些資料。對於第三方應用程式,為了保證URI標識的唯一性,它必須是一個完整的、小寫 類名。這個標識在<provider> 元素的 authorities屬性中說明:
<provider name=”.TransportationProvider” authorities=”com.example.transportationprovider” . . . >
C:路徑,Content Provider使用這些路徑來確定當前需要生什麼類型的資料,URI中可能不包括路徑,也可能包括多個;
D:如果URI中包含,表示需要擷取的記錄的ID;如果沒有ID,就表示返回全部;
由於URI通常比較長,而且有時候容易出錯,切難以理解。所以,在Android當中定義了一些輔助類,並且定義了一些常量來代替這些長字串,例如:People.CONTENT_URI
ContentResolver 介紹說明
看完這些介紹,大家一定就明白了,ContentResolver是通過URI來查詢ContentProvider中提供的資料。除了URI以外,還必須知道需要擷取的資料區段的名稱,以及此資料區段的資料類型。如果你需要擷取一個特定的記錄,你就必須知道目前記錄的ID,也就是URI中D部分。
前面也提到了Content providers是以類似資料庫中表的方式將資料暴露出去,那麼ContentResolver也將採用類似資料庫的操作來從Content providers中擷取資料。現在簡要介紹ContentResolver的主要介面,如下:
傳回值 |
函式宣告 |
final Uri |
insert(Uri url, ContentValues values)Inserts a row into a table at the given URL. |
final int |
delete(Uri url, String where, String[] selectionArgs)Deletes row(s) specified by a content URI. |
final Cursor |
query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)Query the given URI, returning a Cursor over the result set. |
final int |
update(Uri uri, ContentValues values, String where, String[] selectionArgs)Update row(s) in a content URI. |
看到這裡,是否感覺與資料庫的操作基本一樣的。就是這樣的,詳細解析請參考了 Android SQLite解析 中的說明,不在此詳細說明。
最後一個問題:如何擷取ContentResolver。調用getContentResolver (),例如:ContentResolver cr = getContentResolver();
知道ContentResolver是通過ContentProvider來擷取其他與應用程式共用的資料,那麼ContentResolver與ContentProvider的介面應該差不多的。
其中ContentProvider負責
* 組織應用程式的資料;
* 向其他應用程式提供資料;
ContentResolver則負責
* 擷取ContentProvider提供的資料;
* 修改/添加/刪除更新資料等;
ContentProvider 是如何向外界提供資料的。
Android提供了ContentProvider,一個程式可以通過實現一個ContentProvider的抽象介面將自己的資料完全暴露出去,而且ContentProviders是以類似資料庫中表的方式將資料暴露,也就是說ContentProvider就像一個“資料庫”。那麼外界擷取其提供的資料,也就應該與從資料庫中擷取資料的操作基本一樣,只不過是採用URI來表示外界需要訪問的“資料庫”。至於如何從URI中識別出外界需要的是哪個“資料庫”,這就是Android底層需要做的事情了,不在此詳細說。簡要分析下ContentProvider向外界提供資料操作的介面:
query(Uri, String[], String, String[], String)
insert(Uri, ContentValues)
update(Uri, ContentValues, String, String[])
delete(Uri, String, String[])
這些操作與資料庫的操作基本上完全一樣,在此不詳細說,具體的解析可以參考 Android Sqlite解析 中的詳細說明。需要特殊說明的地方是URI:
在URI的D部分可能包含一個_ID ,這個應該出現在SQL語句中的,可以以種特殊的方式出現,這就要求我們在提供資料的時候,需要來額外關注這個特殊的資訊。Android SDK推薦的方法是:在提供資料表欄位中包含一個ID,在建立表時INTEGER PRIMARY KEY AUTOINCREMENT標識此ID欄位。
ContentProvider 是如何組織資料的。
組織資料主要包括:儲存資料,讀取資料,以資料庫的方式暴露資料。資料的儲存需要根據設計的需求,選擇合適的儲存結構,首選資料庫,當然也可以選擇本地其他檔案,甚至可以是網路上的資料。資料的讀取,以資料庫的方式暴露資料這就要求,無論資料是如何儲存的,資料最後必須以資料的方式訪問。
可能還有2個問題,是需要關注的。
1. ContentProvider是什麼時候建立的,是誰建立的。訪問某個應用程式共用的資料,是否需要啟動這個應用程式。這個問題在 Android SDK中沒有明確說明,但是從資料共用的角度出發,ContentProvider應該是Android在系統啟動時就建立了,否則就談不上資料共用了。這就要求在AndroidManifest.XML中使用<provider>元素明確定義。
2. 可能會有多個程式同時通過ContentResolver訪問一個ContentProvider,會不會導致像資料庫那樣的“髒資料”。這個問題一方面需要資料庫訪問的同步,尤其是資料寫入的同步,在AndroidManifest.XML中定義ContentProvider的時候,需要考慮是<provider>元素multiprocess屬性的值;另外一方面Android在ContentResolver中提供了 notifyChange()介面,在資料改變時會通知其他ContentObserver,這個地方應該使用了觀察者模式,在 ContentResolver中應該有一些類似register,unregister的介面。
至此,已經對ContentProvider提供了比較全面的分析,至於如何建立ContentProvider,可通過2種方法:建立一個屬於你自己的ContentProvider或者將你的資料添加到一個已經存在的ContentProvider中,當然前提是有相同資料類型並且有寫入 Content provider的許可權。在Android SDK的sample中提供的 Notepad具體執行個體 中去看原始碼。
轉自:http://www.pin5i.com/showtopic-android-contentresolver-1.html