android contentProvider

除了共享內(nèi)存(SDCard)的數(shù)據(jù)外,其他包括SQLite、SharedPreferences都是僅限于被當(dāng)前所創(chuàng)建的應(yīng)用訪問,而無法使它們的數(shù)據(jù)在應(yīng)用程序之間交換數(shù)據(jù),所以Android提供了ContentProvider,ContentProvider具有以下特點:

  • 應(yīng)用程序間共享數(shù)據(jù)的一種方式
  • 為存儲和獲取數(shù)據(jù)提供統(tǒng)一接口
  • android為一些常見的數(shù)據(jù)提供了ContentProvider:
    • Browser:存儲如瀏覽器的信息。
    • CallLog:存儲通話記錄等信息。
    • Contacts:存儲聯(lián)系人等信息。
    • MediaStore:存儲媒體文件的信息。
    • Settings:存儲設(shè)備的設(shè)置和首選項信息。
ContentProvider可以理解為一個Android應(yīng)用對外開放的接口, 只要是符合它所定義的Uri格式的請求,均可以正常訪問執(zhí)行操作。
訪問ContentProvider

ContentProvider 實例通過處理來自其他應(yīng)用的請求來管理對結(jié)構(gòu)化數(shù)據(jù)集的訪問。所有形式的訪問最終都會調(diào)用 ContentResolver,后者接著調(diào)用ContentProvider的具體方法來獲取訪問權(quán)限

一般使用Context.getContentResolver()方法獲取ContentResolver對象。

ContentResolver 可提供insert、query、update、delete等方法.

例如,要從用戶字典提供程序中獲取字詞及其區(qū)域設(shè)置的列表,則需調(diào)用 ContentResolver.query()。

// Queries the user dictionary and returns results
mCursor = getContentResolver().query(
    UserDictionary.Words.CONTENT_URI,   
    mProjection,                        
    mSelectionClause                  
    mSelectionArgs,                     
    mSortOrder);                        
query() 參數(shù) SELECT 關(guān)鍵字/參數(shù) 備注
Uri FROM table_name Uri 映射至名為 table_name 的提供程序中的表。
projection col,col,col,... projection 是應(yīng)該為檢索到的每個行包含的列的數(shù)組。
selection WHERE col = value selection 會指定選擇行的條件。
selectionArgs (沒有完全等效項。選擇參數(shù)會替換選擇子句中 ? 的占位符。)
sortOrder ORDER BY col,col,... sortOrder 指定行在返回的 Cursor 中的顯示順序。
內(nèi)容 URI

在Android中,Uri是一種比較常見的資源訪問方式。每一個ContentProvider都擁有一個公共的URI,這個URI用于表示這個ContentProvider所提供的數(shù)據(jù)。

<srandard_prefix>://<authority>/<data_path>/<id>

  • <srandard_prefix>:
    ContentProvider的標(biāo)準(zhǔn)前綴始終是content://
  • <authority>:URI 的標(biāo)識,用于唯一標(biāo)識這個ContentProvider,外部調(diào)用者可以根據(jù)這個標(biāo)識來找到它。它定義了是哪個Content Provider提供這些數(shù)據(jù)。對于第三方應(yīng)用程序,為了保證URI標(biāo)識的唯一性,它必須是一個完整的、小寫的類名。一般為該ContentProvider的包.類的名稱
  • <data_path>:請求的數(shù)據(jù)類型, 如數(shù)據(jù)庫的表。
  • <id>:指定請求的特定數(shù)據(jù)。如果URI中包含表示需要獲取的記錄的ID;則就返回該id對應(yīng)的數(shù)據(jù),如果沒有ID,就表示返回全部
content://user_dictionary/words
content://com.example.app.provider/table3/1
//對應(yīng)由 表table3中1標(biāo)識的行的內(nèi)容 URI。
content://com.example.app.provider/table3/1/name
//對應(yīng)由 表table3中1標(biāo)識的行的name字段內(nèi)容 URI。
UriMatcher

UriMatcher會將內(nèi)容 URI“模式”映射到整型值。 可以在一個 switch 語句中使用這些整型值,為匹配特定模式的一個或多個內(nèi)容 URI 執(zhí)行相應(yīng)操作。

內(nèi)容 URI 模式使用通配符匹配內(nèi)容 URI:

*:匹配由任意長度的任何有效字符組成的字符串
#:匹配由任意長度的數(shù)字字符組成的字符串

假設(shè)一個具有權(quán)限 com.example.app.provider的提供程序能識別以下指向表的內(nèi)容 URI:

content://com.example.app.provider/table1:一個名為 table1 的表
content://com.example.app.provider/table2/dataset1:一個名為 dataset1 的表
content://com.example.app.provider/table2/dataset2:一個名為 dataset2 的表
content://com.example.app.provider/table3:一個名為 table3 的表

可以使用以下內(nèi)容 URI 模式:

content://com.example.app.provider/*
//匹配提供程序中的任何內(nèi)容 URI。
content://com.example.app.provider/table2/*:
//匹配表 dataset1 和表 dataset2 的內(nèi)容 URI,但不匹配 table1 或 table3 的內(nèi)容 URI。
content://com.example.app.provider/table3/#
//匹配 table3 中單個行的內(nèi)容 URI,
//如 content://com.example.app.provider/table3/6 對應(yīng)由 6 標(biāo)識的行的內(nèi)容 URI。

方法 addURI() 會將權(quán)限和路徑映射到一個整型值。 方法 match() 會返回 URI 的整型值。switch 語句會在查詢整個表與查詢單個記錄之間進行選擇:

public class ExampleProvider extends ContentProvider {
      ...
    // Creates a UriMatcher object.
    private static final UriMatcher sUriMatcher;

    sUriMatcher.addURI("com.example.app.provider", "table3", 1);

    sUriMatcher.addURI("com.example.app.provider", "table3/#", 2);
    ...
    // Implements ContentProvider.query()
    public Cursor query(Uri uri, String[] projection, String selection, 
                String[] selectionArgs, String sortOrder) {
        ...
        switch (sUriMatcher.match(uri)) {
            // If the incoming URI was for all of table3
            case 1:
                if (TextUtils.isEmpty(sortOrder)) sortOrder = "_ID ASC";
                break;
            // If the incoming URI was for a single row
            case 2:
                /*
                 Because this URI was for a single row, the _ID value part is
                 present. Get the last path segment from the URI;
                 this is the _ID value.Then, append the value to the WHERE 
                 clause for the query
                 */
                selection = selection + "_ID = " uri.getLastPathSegment();
                break;

            default:
            ...
                // If the URI is not recognized, you should do some error handling here.
        }
        // call the code to actually do the query
    }
創(chuàng)建ContentProvider

在Android中,如果要創(chuàng)建自己的內(nèi)容提供者的時候,需要擴展抽象類ContentProvider,并重寫其中定義的各種方法。然后在AndroidManifest.xml文件中注冊該ContentProvider。

創(chuàng)建ContentProvider的步驟:

  1. 創(chuàng)建一個ContentProvider的子類。
  1. 定義內(nèi)容Uri
  1. 創(chuàng)建SQLiteOpenHelper的子類,創(chuàng)建一個用于存儲內(nèi)容的數(shù)據(jù)庫。
  1. 在ContentProvider的子類中實現(xiàn)query()、insert()、update()、delete()、getType()、onCreate()方法。
  1. 在AndroidManifest.xml文件中注冊自定義的ContentProvider。
    <provider.../>:一般只需要設(shè)置兩個屬性即可訪問,一些額外的屬性就是為了設(shè)置訪問權(quán)限而存在的:
    android:name:provider的響應(yīng)類。
    android:authorities:Provider的唯一標(biāo)識,用于Uri匹配,一般為ContentProvider類的全名。

在實現(xiàn)ContentProvider的方法時需要注意一下幾點:

  • 所有這些方法(onCreate() 除外)都可由多個線程同時調(diào)用,因此它們必須是線程安全方法。
  • 避免在 onCreate() 中執(zhí)行長時間操作。將初始化任務(wù)推遲到實際需要時進行。
  • 盡管必須實現(xiàn)這些方法,但代碼只需返回要求的數(shù)據(jù)類型,無需執(zhí)行任何其他操作。 例如,可能想防止其他應(yīng)用向某些表插入數(shù)據(jù)。 要實現(xiàn)此目的,可以忽略 insert() 調(diào)用并返回 0。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 一、使用ContentProvider(內(nèi)容提供者)共享數(shù)據(jù) ContentProvider在android中的作...
    IT楓閱讀 4,492評論 0 7
  • Android數(shù)據(jù)存儲(一) Android數(shù)據(jù)存儲(二) Android數(shù)據(jù)存儲(三) Android數(shù)據(jù)存儲(...
    前端develop閱讀 2,382評論 0 3
  • 這篇主要介紹下ContentProvider如何實現(xiàn)共享數(shù)據(jù)、及ContentResolver如何訪問其他進程等數(shù)...
    朋永閱讀 3,045評論 0 5
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 178,987評論 25 709
  • 不可抗力具有獨特的魔力,它的力量摧枯拉朽。我小時候總做的一個夢,它一直都在預(yù)警著一件可怕的事情。這很奇妙,就好像到...
    DEBRAH閱讀 311評論 0 0

友情鏈接更多精彩內(nèi)容