android資料共用之Content Provider(訪問篇CRUD)

來源:互聯網
上載者:User

5、訪問Content Provider

這裡首先學習如何使用Content provider(包括系統提供的,比如建立一個簡訊收發系統)。

Content Providers的使用者都不可能直接存取到Content Provider執行個體,只能通過ContentResolver在中間代理。用戶端直接使用Content Resolver對象進行互動,Content Resolvers 方法提供了基本的持續儲存資料的函數CRUD(create、retrieve、update和delete)。用戶端如何擷取ContentResolver的執行個體,可通過如下Activity的成員方法擷取。不過當你訪問provider時,你的應用程式應在mainfest檔案請求相應的許可權。

ContentResolver cr= getContext().getContentResolver();

ContentResolver提供了5個基本的對Content Provider操作的方法,後面將會深入介紹。當你建立自己的Content Provider,也就是繼承了ContentProvider類時,意味著你也同時實現這5個方法(在後續章節會介紹到)。

1、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 Cursor managedQuery(Uri uri,String[] projection,String selection,String[]selectionArgs,String sortOrder)2、final Uri insert(Uri url, ContentValues values)//Inserts a row into a table at the given URL.3、final int  update(Uri uri, ContentValues values, String where, String[] selectionArgs)//Update row(s) in a content URI.4、final int  delete(Uri url, String where, String[] selectionArgs)//Deletes row(s) specified by a content URI.5、final String getType(Uri url)//Return the MIME type of the given content URL.

上面面提供的兩種查詢方法,區別在於方法managedQuery()的Cursor的生命週期由activity管理。管理的好處:activity幫你處理細節,如activity暫停時卸載,activity重新開始時重新請求。對於未被activity管理的Cursor可通過此函數讓activit管理:

Activity.startManagingCursor(Cursor cursor)

6、從provider查詢資料

查詢主要下面兩步(以User Dictinary為例)

(1)請求讀取許可權。在mainfest檔案中配置android.permission.READ_USER_DICTIONARY

(2)自訂查詢的代碼。這裡主要有兩種處理方式:一種是顯示查詢的結果,另外一種是擷取查詢的資料。

另外當你精確尋找某一個記錄時,也就意味著你的裡Uri需要包含其_ID值,可以通過以下兩種方法追加,如下:

Uri myPerson = ContentUris.withAppendedId(People.CONTENT_URI, 23);Uri myPerson = Uri.withAppendedPath(People.CONTENT_URI, "23");

6.1 首先需要構造一個查詢

// 指定要返回的每行的欄位String[] mProjection ={    UserDictionary.Words._ID,    // Contract class constant for the _ID column name    UserDictionary.Words.WORD,   // Contract class constant for the word column name    UserDictionary.Words.LOCALE  // Contract class constant for the locale column name};// 定義查詢子句的字串(類似Sql的where子句,但無where關鍵字)String mSelectionClause = null;// 初始化數組,其包含查詢子句的參數值(即選擇字句預留位置“?”值)String[] mSelectionArgs = {""};/* * This defines a one-element String array to contain the selection argument. */String[] mSelectionArgs = {""};// 擷取使用者輸入mSearchString = mSearchWord.getText().toString();//記得檢查使用者輸入有效性// 為空白就用null,代表查詢所有的資料if (TextUtils.isEmpty(mSearchString)) {    mSelectionClause = null;    mSelectionArgs[0] = "";} else {    // 根據使用者輸入構造查詢子句    mSelectionClause = UserDictionary.Words.WORD + " = ?";    // 使用者輸入的字元    mSelectionArgs[0] = mSearchString;}// 通過ContextResolver物件查詢,返回Cursor對象mCursor = 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// 對查詢的cursor處理(空或者異常等)if (null == mCursor) {    /*     * 處理錯誤,此時mCursor不能使用     * call android.util.Log.e() to log this error.     *     */// If the Cursor is empty, the provider found no matches} else if (mCursor.getCount() < 1) {    /*     * 查詢失敗,通知使用者無效查詢子句     * 也有可能是你想推薦給使用者的輸入     */} else {    // 處理正確的查詢結果}

註:使用預留位置“?”,可以有效阻止惡意的SQL語句,也就是為什麼間接使用mSelectionClause和mSelectionArgs來構造where語句的原因。

 

6.2.1顯示查詢結果

查詢返回的是Cursor,此物件類型是列表行,因此顯示Cursor內容最好憑藉SimpleCursorAdapter填充器將之連結到ListView上。

(1)如果不匹配selection,provider返回空的Cursor對象,此時Cursor.getCount()為0

(2)如果發生內部錯誤,查詢結果取決於provider(可能返回null,也可能為Exception)

// 定義從Cursor返回的欄位列String[] mWordListColumns ={    UserDictionary.Words.WORD,   // Contract class constant containing the word column name    UserDictionary.Words.LOCALE  // Contract class constant containing the locale column name};// 定義返回欄位將要填充的View的id,也就是int to[]int[] mWordListItems = { R.id.dictWord, R.id.locale};// Creates a new SimpleCursorAdaptermCursorAdapter = new SimpleCursorAdapter(    getApplicationContext(),               // The application's Context object    R.layout.wordlistrow,                  // A layout in XML for one row in the ListView    mCursor,                               // The result from the query    mWordListColumns,                      // A string array of column names in the cursor    mWordListItems,                        // An integer array of view IDs in the row layout    0);                                    // Flags (usually none are needed)// Sets the adapter for the ListViewmWordList.setAdapter(mCursorAdapter);

6.2.2 從查詢結果中擷取資料

// 擷取該欄位的索引int index = mCursor.getColumnIndex(UserDictionary.Words.WORD);/* * 如果cursor有效時才執行,可能返回null、內部錯誤或者Exception */if (mCursor != null) {    /*     * 在執行while語句即移動前,應首先在這裡將cursor移動到下一行     *如果嘗試直接查詢資料,將會獲得異常, 因為"row pointer" 是 -1       */    while (mCursor.moveToNext()) {        // 從欄位索引中擷取相應的值        newWord = mCursor.getString(index);        // 處理查詢的值.        ...        // end of while loop    }} else {    //如果cursor為null或者provider扔出exception,處理}

6.3插入資料:

使用ContentResolver.insert()方法,其插入新行到provider,同時返回新加行的URI

// 定義一個新的Uri對象,其接收插入的結果Uri mNewUri;...// 定義一個對象用來暫存需插入的值ContentValues mNewValues = new ContentValues();/* * 設定插入的每一個欄位的值,參數:欄位名,欄位值 */mNewValues.put(UserDictionary.Words.APP_ID, "example.user");mNewValues.put(UserDictionary.Words.LOCALE, "en_US");mNewValues.put(UserDictionary.Words.WORD, "insert");mNewValues.put(UserDictionary.Words.FREQUENCY, "100");mNewUri = getContentResolver().insert(    UserDictionary.Word.CONTENT_URI,   // the user dictionary content URI    mNewValues                          // the values to insert);

註:(1)由於SQLite資料庫特性,這裡不需要放置與欄位相同類型的資料,甚至你可以不需要指定值,使用ContentValues.putNull()。

(2)主鍵自動成長(autoincrement),provider分配給每一行獨一的_ID,用作主鍵。

(3)返回的新的URI如下,<id_value>就是_ID值,可利用該id對此行執行相應操作。擷取此_ID值,通過ContentUris.parseId();

content://user_dictionary/words/<id_value>

6.4更新資料

用戶端使用ContentResolver.update()更新資料,返回更新的行數。利用ContentValues對象暫存資料,其中只需要儲存想改變的欄位。若想清除,直接設定值為null就可以了。

// 定義ContentValues對象,暫存需更新的資料ContentValues mUpdateValues = new ContentValues();// 定義想更新的行的查詢子句String mSelectionClause = UserDictionary.Words.LOCALE +  "LIKE ?";String[] mSelectionArgs = {"en_%"};// 定義一變數,儲存被更新的行的總數int mRowsUpdated = 0;.../* * 需更新值得儲存 */mUpdateValues.putNull(UserDictionary.Words.LOCALE);mRowsUpdated = getContentResolver().update(    UserDictionary.Words.CONTENT_URI,   // the user dictionary content URI    mUpdateValues                       // the columns to update    mSelectionClause                    // the column to select on    mSelectionArgs                      // the value to compare to);

6.5刪除資料

類似於查詢,指定想刪除行的條件,同時將返回刪除的行數。執行刪除操作時,應當對使用者的輸入採取一定錯數,以防惡意輸入。

// 定義刪除條件String mSelectionClause = UserDictionary.Words.APP_ID + " LIKE ?";String[] mSelectionArgs = {"user"};// 定義變數,儲存刪除的行數int mRowsDeleted = 0;...// 刪除mRowsDeleted = getContentResolver().delete(    UserDictionary.Words.CONTENT_URI,   // the user dictionary content URI    mSelectionClause                    // the column to select on    mSelectionArgs                      // the value to compare to);

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.