《第一行代碼》第七章 訪問其他程序中的數(shù)據(jù)

7.3.1 ContentResolver的基本用法

通過借助ContentResolver類訪問內(nèi)容提供器中共享的數(shù)據(jù),可以通過Context中的getContentResolver()方法獲取該類實(shí)例。

ContentResolver中的增刪改查方法都不接收表名參數(shù),而是使用一個Uri參數(shù)代替,這個參數(shù)被稱為內(nèi)容URI。內(nèi)容URI給內(nèi)容提供器中的數(shù)據(jù)建立了唯一一個標(biāo)識符,主要由兩部分組成:authority和path。authority是用于對不同的應(yīng)用程序作區(qū)分的,采用程序包和路徑的命名方式進(jìn)行命名。比如某個程序包的名是

com.example.app

那么該程序?qū)?yīng)的authority就可以命名為

com.example.app.provider

path則是用于對同一應(yīng)用程序中不同的表作區(qū)分的,通常都會添加到authority的后面。比如某個程序的數(shù)據(jù)庫里存在兩張表:table1和table2,這是就可以將path分別命名為/table1和/table2,然后把a(bǔ)uthority和path進(jìn)行組合,內(nèi)容URI就變成了

com.example.app.provider/table1

com.example.app.provider/table2

不過,還很難辨認(rèn)出這兩個字符串就是兩個內(nèi)容URI,我們還需要在字符串的頭部加上協(xié)議聲明。因此,內(nèi)容URI最標(biāo)準(zhǔn)的格式寫法如下:

content://com.example.app.provider/table1
content://com.example.app.provider/table2

之后我們還需要將它解析成Uri對象才可以作為參數(shù)傳入:

Uri uri = Uri.parse("content://com.example.app.provider/table1")

現(xiàn)在可以使用這個Uri對象來查詢table1表中的數(shù)據(jù)了:

Cursor cursor = getContentResolver().query(
    uri,
    projection,
    selection,
    selectionArgs,
    sortOrder);

查詢完成后仍返回一個Cursor對象,這是我們就可以將數(shù)據(jù)從Cursor對象中逐個讀取出來了。讀取的思路仍然是通過移動游標(biāo)的位置來遍歷Cursor的所有航,然后再取出每一行中相應(yīng)列的數(shù)據(jù),代碼如下:

if (cursor != null) {
    while (cursor.moveToNext()) {
        String column1 = cursor.getString(cursor.getColumnIndex("column1"));
        int column2 = cursor.getInt(cursor.getColumnIndex("column2"));
        }
        cursor.close();
}

7.4 創(chuàng)建內(nèi)容提供器的步驟

如果想要實(shí)現(xiàn)跨程序貢獻(xiàn)數(shù)據(jù)的功能,官方推薦的方式就是使用內(nèi)容提供器,可以通過新建一個類去繼承ContentProvider的方式來創(chuàng)建一個自己的內(nèi)容提供器。ContentProvider類中有6個抽象方法,我們在使用子類繼承它的時候,需要將6個方法全部重寫。
每一個方法都會帶有Uri這個參數(shù),這個參數(shù)也正是調(diào)用ContentResolver的增刪改查方法時傳遞過來的,我們需要對傳入的Uri參數(shù)進(jìn)行解析,從中分析出調(diào)用方期望訪問的表和數(shù)據(jù),一個標(biāo)準(zhǔn)內(nèi)容的URI寫法是這樣的:

content://com.example.app.provider/table1

這樣表示調(diào)用方期望訪問的是com.example.app這個應(yīng)用的tale1表中的數(shù)據(jù)。除此之外,我們還可以在這個內(nèi)容URI的后面加上一個id,如下所示:

content://com.example.app.provider/table1/1

這就表示調(diào)用方期望訪問得失com.example.app這個應(yīng)用的table1表中的id為1的數(shù)據(jù)。我們可以使用通配符的方式來分別匹配這兩種格式的內(nèi)用URI,規(guī)則如下:

  • *:表示匹配任意長度的任意字符。
  • #:表示匹配任意長度的數(shù)字。
    所以,一個能夠匹配任意表的內(nèi)容URI格式就可以寫成:
content://com.example.app.provider/*

而一個能夠匹配table1表中任意一行數(shù)據(jù)的內(nèi)容URI格式就可以寫成:

content://com.example.app.provider/table1/#

接著,我們在借助UriMatcher這個類就可以輕松地實(shí)現(xiàn)匹配內(nèi)容URI的功能。UriMatcher中提供了一個addURI()方法,這個方法接收3個參數(shù),可以分別吧authority、path和一個自定義代碼轉(zhuǎn)進(jìn)去。這樣,當(dāng)調(diào)用UriMatcher的match()方法時,就可以將一個Uri對象傳入,返回值是某個能夠匹配這個Uri對象所對應(yīng)的自定義代碼,利用這個代碼,我們可以判斷出調(diào)用方期望訪問的事那張表中的數(shù)據(jù)了。

getType()方法是所有內(nèi)容提供器都必須提供的一個方法,用于獲取Uri對象所對應(yīng)的MIME類型。一個融融URI多對應(yīng)的MIME字符串主要由3個部分組成,Android對這3個部分做了如下格式規(guī)定。

  • 必須以vnd開頭。
  • 如果內(nèi)容URI以路徑結(jié)尾,則后接android.cursor.dir/,如果內(nèi)容URI以id結(jié)尾,則后接android.cursor.item/。
  • 最后接上vnd.<authority>.<path>。
    所以,對于content://com.example.app.provider/table1這個內(nèi)容URI,它所對應(yīng)的MIME類型就可以寫成:
vnd.android.cursor.dir/vnd.com.example.app.provider.table1

對于content://com.example.app.provider.table1/1這個內(nèi)容URI,它所對應(yīng)的MIME類型就可以寫成:

vnd.android.cursor.item/vnd.com.example.app.provider.table1
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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