-
內容提供器介紹##
-
內容提供器用法##
- 內容提供器介紹
內容提供者主要用于在不同的應用程序之間實現數據共享的功能,它提供了一套完整的機制,允許一個程序訪問另一個程序中的數據,同時還能保證被訪數據的安全性。內容提供其可以選擇只對哪一部分數據進行共享。 - 內容提供器用法
1)訪問其他程序中的數據
當一個應用程序通過內容提供器對其數據對其數據提供了外部訪問接口,任何其他應用程序就可以對這部分數據進行訪問。 - ContentResolver
若想訪問內容提供器中共享的數據,就一定要借助ContentResolver類。ContentResolver 中提供了一系列的方法用于對數據進行 CRUD 操作,其中 insert()方法用于
添加數據,update()方法用于更新數據,delete()方法用于刪除數據,query()方法用于查詢數
據。有沒有似曾相識的感覺?沒錯,SQLiteDatabase中也是使用的這幾個方法來進行 CRUD
操作的,只不過它們在方法參數上稍微有一些區別
ContentResolver 中的增刪改查方法都是不接收表名參數的,而
是使用一個 Uri 參數代替,這個參數被稱為內容 URI。內容 URI 給內容提供器中的數據建立
了唯一標識符,它主要由兩部分組成,權限(authority)和路徑(path) 。權限是用于對不同
的應用程序做區分的,一般為了避免沖突,都會采用程序包名的方式來進行命名。比如某個
程序的包名是 com.example.app,那么該程序對應的權限就可以命名為 com.example.app.
provider。路徑則是用于對同一應用程序中不同的表做區分的,通常都會添加到權限的后面。
比如某個程序的數據庫里存在兩張表,table1 和 table2,這時就可以將路徑分別命名為/table1
和/table2,然后把權限和路徑進行組合,內容 URI 就變成了 com.example.app.provider/table1
和 com.example.app.provider/table2。不過,目前還很難辨認出這兩個字符串就是兩個內容
URI,我們還需要在字符串的頭部加上協議聲明。因此,內容 URI 最標準的格式寫法如下:
content://com.example.app.provider/table1
content://com.example.app.provider/table2
Uri uri = Uri.parse("content:\\\\com.example/app.provider/table1");
Cursor cursor = getContentResolver().query(uri,projection,selection,selectionArgs,sortOrder);
這些參數和 SQLiteDatabase 中 query()方法里的參數很像,但總體來說要簡單一些,畢
竟這是在訪問其他程序中的數據,沒必要構建過于復雜的查詢語句。下表對使用到的這部分
參數進行了詳細的解釋。
query() 方法參數 | 對應 SQL 部分 | 描述 |
---|---|---|
uri | from table_name | 指定查詢某個應用程序下的某一張表 |
projection | select column1, column2 | 指定查詢的列名 |
selection | where column = value | 指定 where的約束條件 |
selectionArgs | - | 為 where中的占位符提供具體的值 |
orderBy | order by column1, column2 | 指定查詢結果的排序方式 |
查詢完成后返回的仍然是一個 Cursor 對象,這時我們就可以將數據從 Cursor 對象中逐
個讀取出來了。 讀取的思路仍然是通過移動游標的位置來遍歷 Cursor 的所有行, 然后再取出
每一行中相應列的數據,代碼如下所示:
if (cursor != null) {
while (cursor.moveToNext()) {
String column1 = cursor.getString(cursor.getColumnIndex("column1"));
int column2 = cursor.getInt(cursor.getColumnIndex("column2"));
}
cursor.close();
}
掌握了最難的查詢操作,剩下的增加、修改、刪除操作就更不在話下了。我們先來看看
如何向 table1 表中添加一條數據,代碼如下所示:
ContentValues values = new ContentValues();
values.put("column1", "text");
values.put("column2", 1);
getContentResolver().insert(uri, values);
可以看到,仍然是將待添加的數據組裝到 ContentValues 中,然后調用 ContentResolver
的 insert()方法,將 Uri 和 ContentValues作為參數傳入即可。
現在如果我們想要更新這條新添加的數據,把 column1 的值清空,可以借助
ContentResolver 的 update()方法實現,代碼如下所示:
ContentValues values = new ContentValues();
values.put("column1", "");
getContentResolver().update(uri, values, "column1 = ? and column2 = ?", new
String[] {"text", "1"});
注意上述代碼使用了 selection 和 selectionArgs 參數來對想要更新的數據進行約束, 以防
止所有的行都會受影響。
最后,可以調用 ContentResolver 的 delete()方法將這條數據刪除掉,代碼如下所示:
getContentResolver().delete(uri, "column2 = ?", new String[] { "1" });
- 自定義內容提供器
- onCreate()
初始化內容提供器的時候調用。通常會在這里完成對數據庫的創建和升級等操作,
返回 true 表示內容提供器初始化成功,返回 false 則表示失敗。注意,只有當存在
ContentResolver 嘗試訪問我們程序中的數據時,內容提供器才會被初始化。 - query()
從內容提供器中查詢數據。使用 uri 參數來確定查詢哪張表,projection 參數用于確
定查詢哪些列,selection 和 selectionArgs 參數用于約束查詢哪些行,sortOrder 參數用于
對結果進行排序,查詢的結果存放在 Cursor 對象中返回。 - insert()
向內容提供器中添加一條數據。使用 uri 參數來確定要添加到的表,待添加的數據
保存在 values 參數中。添加完成后,返回一個用于表示這條新記錄的 URI。 - update()
更新內容提供器中已有的數據。使用 uri 參數來確定更新哪一張表中的數據,新數
據保存在 values 參數中,selection 和 selectionArgs 參數用于約束更新哪些行,受影響的
行數將作為返回值返回。 - delete()
從內容提供器中刪除數據。使用 uri 參數來確定刪除哪一張表中的數據,selection
和 selectionArgs 參數用于約束刪除哪些行,被刪除的行數將作為返回值返回。 - getType()
根據傳入的內容 URI 來返回相應的 MIME 類型。
注意:
getType()方法是所有內容提供器都必須提供的一個方法,用于獲取Uri對象所對應的MIME類型。一個內容URI所對應的MIME字符串主要由三部分組成。
1.必須以vnd開頭
2.如果內容URI以路徑結尾,則后接android.cursor.dir/,如果內容URI以id結尾,則后接android.cursor.item/
3.最后接上vnd.<authority>.<path>
對于 content://com.example.app.provider/table1 這個內容 URI,它所對應的 MIME
類型就可以寫成:
vnd.android.cursor.dir/vnd.com.example.app.provider.table1
對于 content://com.example.app.provider/table1/1 這個內容 URI,它所對應的 MIME 類型
就可以寫成:
vnd.android.cursor.item/vnd. com.example.app.provider.table1
AndroidManfest.xml配置provider
<provider android:name="com.xxx.MyProvider"
android:authorities="com.example.databasetest.provider >
</provider>