標籤:des android style class c blog
Android Content Provider Guides
Content Providers管理對結構化資料集的訪問。它們封裝資料,並且提供一種定義資料安全的機制。
Content providers是不同進程間資料連線的標準介面。
要擷取content provider中的資料,需要運用你的應用中的 Context中的ContentResolver對象作為一個client來和provider互動。
這個provider對象是一個實現了ContentProvider介面的類的對象。Provider對象從clients那裡擷取資料請求,執行請求的動作,然後返回結果。
如果你不想和其他的應用分享資料,你就不必開發自己的provider,但是,如果你需要在應用中提供自訂的搜尋建議,或者你需要從你的應用複製粘貼複雜的資料和檔案到其他的應用,你還是需要開發自己的provider。
Android系統包含了管理各種資料的content provider,可管理的資料包括音頻、視頻、映像、個人通訊資訊等。可以看看這個包: android.provider。在一些限制條件下,這些providers是可以被任何Android應用訪問的。
Content Provider Basics
Content Provider管理對中央資料庫的訪問,是Android應用的一部分,經常會提供一些UI來操作資料。
然而,content providers主要是用來被其他應用使用的,其他應用通過一個client對象來訪問provider。
providers和provider clients一起,提供了持續、標準的介面來訪問資料,其中還包含了一些跨進程通訊和資料訪問安全相關的東西。
Content provider向外部應用呈現資料的方式像關係型資料庫中的表(但是底層實現並不一定要求是資料庫)。
provider沒有要求必須有主鍵,也沒有要求必須有一列叫_ID,然而,如果想要綁定資料到ListView中,就得有一列叫_ID。
訪問provider
一個應用想要訪問content provider中的資料,需要通過一個 ContentResolver用戶端對象。
這個用戶端對象中有一些方法會調用provider對象中的同名方法。
provider對象是 ContentProvider的實作類別的執行個體。
ContentResolver中的方法提供了基本的“CRUD”(create, retrieve, update, and delete)資料操作。
ContentResolver 對象在用戶端應用的進程中, ContentProvider對象在擁有provider的應用中,它們會自動處理跨進程通訊。 ContentProvider 也是一個抽象層,處在資料倉儲(底層)和資料表(外部表格現)之間。
為了訪問provider,應用通常需要聲明一些許可權,見 Content Provider Permissions。
Content URI
Content URI中包含了provider的符號名(authority)和一個指向資料表的路徑名(path)。
當你調用用戶端方法來訪問provider中的表的時候,參數中會需要一個content URI。
ContentResolver對象會解析URI的authority,使用它和系統已知的providers的表做對比,來resolve出provider。
之後 ContentResolver就可以把查詢的參數分發給正確的provider了。
ContentResolver會使用content URI的path來選擇要訪問的table,一個provider通常會為每一個table提供一個path。
比如:
content://user_dictionary/words
user_dictionary是authority,words是table的path。
content:// (the scheme)說明這個字串是一個content URI。
很多providers會允許在URI後面加上ID值來訪問table中的行。
一些有用的類:Uri Uri.Builder ContentUris
Retrieving Data from the Provider
資料查詢操作通常需要在一個非UI的線程非同步執行,可以參考Loaders guide。
從一個provider中查詢資料,通常需要兩步:
1.擷取這個provider的讀許可權;
2.定義好向這個provider查詢語句。
官方Guides裡寫了例子,還講了防SQL注入等相關的考慮。
/* * This defines a one-element String array to contain the selection argument. */String[] mSelectionArgs = {""};// Gets a word from the UImSearchString = mSearchWord.getText().toString();// Remember to insert code here to check for invalid or malicious input.// If the word is the empty string, gets everythingif (TextUtils.isEmpty(mSearchString)) { // Setting the selection clause to null will return all words mSelectionClause = null; mSelectionArgs[0] = "";} else { // Constructs a selection clause that matches the word that the user entered. mSelectionClause = UserDictionary.Words.WORD + " = ?"; // Moves the user‘s input string to the selection arguments. mSelectionArgs[0] = mSearchString;}// Does a query against the table and returns a Cursor objectmCursor = getContentResolver().query( UserDictionary.Words.CONTENT_URI, // The content URI of the words table mProjection, // The columns to return for each row mSelectionClause // Either null, or the word the user entered mSelectionArgs, // Either empty, or the string the user entered mSortOrder); // The sort order for the returned rows// Some providers return null if an error occurs, others throw an exceptionif (null == mCursor) { /* * Insert code here to handle the error. Be sure not to use the cursor! You may want to * call android.util.Log.e() to log this error. * */// If the Cursor is empty, the provider found no matches} else if (mCursor.getCount() < 1) { /* * Insert code here to notify the user that the search was unsuccessful. This isn‘t necessarily * an error. You may want to offer the user the option to insert a new row, or re-type the * search term. */} else { // Insert code here to do something with the results}
Displaying query results
查詢的結果是一個 Cursor ,包含了滿足查詢條件的行,projection所指定的列。
如果沒有滿足條件的行,會返回一個空Cursor( Cursor.getCount() 為0)。
如果查詢時發生了內部錯誤,根據具體provider,結果會有所不同,有可能會返回null,或者有可能會拋出異常。
Cursor對象提供對其包含行列的隨機訪問。
使用Cursor中的方法,你可以遍曆結果中的行,得到每一列的資料類型,得到某一列資料,查看結果的其他屬性等等。
一些 Cursor的實作類別會在provider資料變化時自動更新資料,或者在Cursor改變時激發一些觀察者方法,或這兩都有。
展示查詢資料可以用 CursorAdapter或用SimpleCursorAdapter綁定到ListView中去。
要綁定Cursor資料到ListView中,cursor必須包含一列叫_ID。
Inserting, Updating, and Deleting Data
Insert
插入資料用 ContentResolver.insert():這個方法會返回新插入的行的URI,比如:content://user_dictionary/words/<id_value>
資料是放在ContentValues類的對象中,_ID列是provider自動維護的不需要自己寫,providers通常會將_ID作為主鍵。
為了從URI中擷取id,可以調用 ContentUris.parseId()方法。
Update
Update的時候,首先根據選擇條件進行查詢,然後對其中的值變更,和插入一樣,採用ContentValues對象。
採用的方法是 ContentResolver.update()。
Delete
刪除和查詢差不多,設定選擇條件,然後找到要刪除的行,用戶端方法會返回刪除的行的個數。
刪除用的方法是 ContentResolver.delete()。
更新和刪除的時候都要注意是否有使用者的惡意操作,參見:Protecting against malicious input.。
參考資料
API Guides: Content Providers
http://developer.android.com/guide/topics/providers/content-providers.html
Content Provider Basics
http://developer.android.com/guide/topics/providers/content-provider-basics.html