ContentProvider基礎(chǔ)

0x00 前言

這篇關(guān)于 ContentProvider 的總結(jié)文章峻呛,早在四月份就想寫了迫肖,但是一直沒有時(shí)間和精力去寫景醇,而且我也不想隨便寫一下欲侮,還是希望能保證一定的文章質(zhì)量崭闲。恰巧昨天為自己定了一個(gè)目標(biāo),就是每周學(xué)習(xí)一個(gè)主題威蕉,并輸出相關(guān)總結(jié)文章或例程刁俭。所以,第一周的主題就定為ContentProvider韧涨。下面看下本文會(huì)涉及到的幾點(diǎn)內(nèi)容:

  1. 什么是 ContentProvider牍戚;
  2. 使用 ContentProvider 的優(yōu)點(diǎn);
  3. 一個(gè)使用系統(tǒng) ContentProvider 的例程虑粥。

0x01 ContentProvider簡(jiǎn)介

關(guān)于 ContentProvider翘魄,搞 Android 的人都不會(huì)陌生,它是 Andriod 中的四大組件之一舀奶,但或許是存在感最低的一個(gè)組件暑竟。為什么這么說呢?因?yàn)橐话銇碚f我們開發(fā)應(yīng)用很少會(huì)去自定義這種組件育勺,但是其實(shí)它非常重要和有用但荤。我們先來看下它的作用:

一看到它的名字——內(nèi)容提供者,就能大概猜到它與數(shù)據(jù)是相關(guān)的涧至,它的作用就是實(shí)現(xiàn)數(shù)據(jù)共享腹躁,這個(gè)共享不僅僅限于本應(yīng)用內(nèi)部,還包括系統(tǒng)中的其他應(yīng)用(即跨進(jìn)程的數(shù)據(jù)共享)南蓬。為此纺非,它實(shí)現(xiàn)了一套標(biāo)準(zhǔn)的接口方法用于存取(增、刪赘方、改烧颖、查,這些操作其實(shí)和標(biāo)準(zhǔn)的 SQL 操作是類似的)它管理的數(shù)據(jù)窄陡,而底層的數(shù)據(jù)如何存儲(chǔ)(存儲(chǔ)于文件系統(tǒng)或者 SQLite 數(shù)據(jù)庫(kù)等)炕淮,調(diào)用者根本不用去關(guān)心:

// 查詢記錄
Cursor query (Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)

// 插入記錄
Uri insert (Uri uri, ContentValues values)

// 更新記錄
int update (Uri uri, ContentValues values, String selection, String[] selectionArgs)

// 刪除記錄            
int delete (Uri uri, String selection, String[] selectionArgs)

雖然 ContentProvider 定義了一系列的方法,但是我們的應(yīng)用并不直接調(diào)用這些方法跳夭,而是使用一個(gè)ContentResolver對(duì)象涂圆,通過調(diào)用它的方法(與 ContentProvider 中的方法一一對(duì)應(yīng))作為替代们镜,如圖1所示。


ContentResolver.png

圖 1:圖片來自 Udacity 學(xué)院課程截圖

說到這里大家肯定會(huì)奇怪润歉,ContentResolver 是如何定位到我們想要的那個(gè)的ContentProvider 的呢模狭?你要知道Android系統(tǒng)已經(jīng)為我們提供了很多的 ContentProvider,例如日歷踩衩、聯(lián)系人胞皱、多媒體(音頻、視頻以及圖像)等數(shù)據(jù)九妈。

其實(shí)反砌,答案就是各個(gè)方法參數(shù)中的 Uri,就像你在瀏覽器的地址欄中輸入一個(gè)網(wǎng)址 (URL)萌朱,按下回車后宴树,瀏覽器就會(huì)向服務(wù)器發(fā)起請(qǐng)求,而對(duì)應(yīng)的服務(wù)器會(huì)返回相應(yīng)的結(jié)果給瀏覽器晶疼。類似地酒贬,當(dāng)ContentResolver也是通過一個(gè)給定的 URI (UR L是 URI 的一個(gè)子集)發(fā)起請(qǐng)求,Android 系統(tǒng)會(huì)根據(jù)給定URI中的authority(URI 的組成部分找到那個(gè) ContentProvider 翠霍,并將該請(qǐng)求傳遞給該 ContentProvider锭吨。每個(gè) ContentProvider 的 authority 都是唯一的,而且都會(huì)在 Android 系統(tǒng)注冊(cè)寒匙。ContentProvider 收到請(qǐng)求后零如,會(huì)解析 URI 剩余的部分(通過輔助類UriMatcher實(shí)現(xiàn)),然后返回相應(yīng)數(shù)據(jù)锄弱。

通過以上內(nèi)容考蕾,我想大家對(duì) ContentProvider 應(yīng)該有了一個(gè)大概的了解了吧,下面我將通過用戶詞典(user dictionary:用于存儲(chǔ)一些用戶想保存的非標(biāo)準(zhǔn)單詞的拼寫)這個(gè)系統(tǒng)內(nèi)置的 ContentProvider來向大家說明如何使用它会宪。

0x02 如何使用 ContentProvider

我們要知道 ContentProvider 提供的數(shù)據(jù)的形式與一般關(guān)系型的數(shù)據(jù)庫(kù)是一樣的肖卧,都是通過一張或多張的數(shù)據(jù)庫(kù)表來實(shí)現(xiàn)的,例如用戶詞典的數(shù)據(jù)表是這樣的掸鹅,其中每一行代碼一個(gè)單詞實(shí)例塞帐,每一列代表每個(gè)單詞的屬性:

表1:用戶詞典數(shù)據(jù)表樣例引用

word app id frequency locale _ID
mapreduce user12 100 en_US 1
applet user2 200 pt_BR 2
const user1 255 en_UK 3

上面這個(gè)表跟我們平時(shí)操作的數(shù)據(jù)表沒有什么區(qū)別嘛,說下本節(jié)我們要實(shí)現(xiàn)的功能就是通過一個(gè)ListView來顯示表1中的數(shù)據(jù)巍沙,就這么簡(jiǎn)單葵姥,具體步驟如下:

(1) 獲取相應(yīng) ContentProvider 的權(quán)限

Android 系統(tǒng)中內(nèi)置了很多的 ContentProvider,當(dāng)我們?cè)L問它們時(shí)赎瞎,需要在AndroidManifest.xml文件中聲明相應(yīng)的讀/寫權(quán)限牌里,如果你聲明了寫權(quán)限颊咬,應(yīng)該不需要再申請(qǐng)讀權(quán)限务甥,用戶詞典的具體權(quán)限聲明如下所示:

<uses-permission android:name="android.permission.READ_USER_DICTIONARY"/>
<uses-permission android:name="android.permission.WRITE_USER_DICTIONARY" />

(2) 訪問正確的 ContentProvider

如前面所述牡辽,我們的應(yīng)用不會(huì)直接訪問 ContentProvider,我們需要通過 ContentResolver 以及正確的 URI敞临,如圖2所示态辛,同時(shí)調(diào)用相應(yīng)的方法:
queryinsert挺尿、updatedelete奏黑。


query.png

圖 2:圖片來自 Udacity 學(xué)院課程截圖

我們這個(gè)例子只是簡(jiǎn)單地查詢數(shù)據(jù),具體示例代碼如下所示:

// 獲取 ContentResolver 用于向 ContentProvider 發(fā)送數(shù)據(jù)請(qǐng)求
ContentResolver resolver = getContentResolver();
// 獲取 Cursor编矾,它包含了Words數(shù)據(jù)表的所有行
Cursor cursor = resolver.query(UserDictionary.Words.CONTENT_URI, // Uri
    null, // projection
    null, // selection
    null, // selectionArgs
    null  // sortOrder
);
Content URI

上述代碼中query方法第一個(gè)參數(shù)UserDictionary.Words.CONTENT_URI熟史,即之前我們提到的 URI,它一般由三部分組成content://authority/path窄俏,它用于標(biāo)識(shí) ContentProvider 中的數(shù)據(jù)記錄蹂匹,詳細(xì)請(qǐng)參考Content URIs

(3) 在 UI 上展現(xiàn)數(shù)據(jù)

我們的目標(biāo)是在 ListView 中顯示這些單詞凹蜈,在第(2)個(gè)步驟得到的cursor其實(shí)就相當(dāng)于一個(gè)數(shù)據(jù)源限寞,所以只要實(shí)現(xiàn)相應(yīng)的 Adapter 即可,具體代碼如下所示:

// 使用系統(tǒng)提供的 SimpleCursorAdapter
SimpleCursorAdapter adapter = new SimpleCursorAdapter(this,
    android.R.layout.two_line_list_item,
    cursor,
    COLUMNS_TO_BE_BOUND,
    LAYOUT_ITEMS_TO_FILL,
    0
);

dictListView.setAdapter(adapter);

0x03 總結(jié)

根據(jù)以上這些的內(nèi)容仰坦,我們稍微總結(jié)一下使用 ContentProvider 的兩個(gè)優(yōu)點(diǎn):

  1. 底層的數(shù)據(jù)源對(duì)上層是透明的履植,可以非常方便地替換;
  2. 允許系統(tǒng)中的多個(gè)應(yīng)用對(duì)同一個(gè)數(shù)據(jù)源進(jìn)行(安全的)訪問和修改悄晃,而相應(yīng)的修改對(duì)于多個(gè)應(yīng)用來說都是可見的玫霎。

看到這里我想很多人會(huì)想:如果我們并不想與其他應(yīng)用共享我們的應(yīng)用的數(shù)據(jù),那么我們應(yīng)該是不需要開發(fā)這種類型的組件妈橄。以前我也是這么想的鼠渺,既然 ContentProvider 底層數(shù)據(jù)的存儲(chǔ)還是通過 SQLite 數(shù)據(jù)庫(kù),為什么要用它呢眷细?其實(shí)不然拦盹,首先我們使用 SQLite 數(shù)據(jù)庫(kù)存儲(chǔ)我們的數(shù)據(jù),我們還是需要在 SQLite 數(shù)據(jù)庫(kù)之上封裝一層類似 ContentProvider 提供的那套接口方法溪椎;其次普舆,我們還可以利用 Android 系統(tǒng)提供的一些相關(guān)功能類與 ContentProvider 配合起來使用。 例如校读,SyncAdaters, Loaders, CursorAdapter沼侣。說到這里我推薦大家一個(gè)視頻吧,來自2010年 Google IO 大會(huì)歉秫,講的是 Android 應(yīng)用的設(shè)計(jì)模式(架構(gòu))蛾洛,其中一共提出了三種設(shè)計(jì)模式,而 ContentProvider 在其中扮演了非常重要的角色:

  1. Android REST client applications
  2. PPT下載地址

0x04 參考資料:

  1. Content Provider
  2. How to Use Content Provider
  3. ContentResolver
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市轧膘,隨后出現(xiàn)的幾起案子钞螟,更是在濱河造成了極大的恐慌,老刑警劉巖谎碍,帶你破解...
    沈念sama閱讀 217,826評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件鳞滨,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡蟆淀,警方通過查閱死者的電腦和手機(jī)拯啦,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,968評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來熔任,“玉大人褒链,你說我怎么就攤上這事∫商Γ” “怎么了碱蒙?”我有些...
    開封第一講書人閱讀 164,234評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)夯巷。 經(jīng)常有香客問我赛惩,道長(zhǎng),這世上最難降的妖魔是什么趁餐? 我笑而不...
    開封第一講書人閱讀 58,562評(píng)論 1 293
  • 正文 為了忘掉前任喷兼,我火速辦了婚禮,結(jié)果婚禮上后雷,老公的妹妹穿的比我還像新娘季惯。我一直安慰自己,他們只是感情好臀突,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,611評(píng)論 6 392
  • 文/花漫 我一把揭開白布勉抓。 她就那樣靜靜地躺著,像睡著了一般候学。 火紅的嫁衣襯著肌膚如雪藕筋。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,482評(píng)論 1 302
  • 那天梳码,我揣著相機(jī)與錄音隐圾,去河邊找鬼。 笑死掰茶,一個(gè)胖子當(dāng)著我的面吹牛暇藏,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播濒蒋,決...
    沈念sama閱讀 40,271評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼盐碱,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起瓮顽,我...
    開封第一講書人閱讀 39,166評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤县好,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后趣倾,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體聘惦,經(jīng)...
    沈念sama閱讀 45,608評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡某饰,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,814評(píng)論 3 336
  • 正文 我和宋清朗相戀三年儒恋,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片黔漂。...
    茶點(diǎn)故事閱讀 39,926評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡诫尽,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出炬守,到底是詐尸還是另有隱情牧嫉,我是刑警寧澤,帶...
    沈念sama閱讀 35,644評(píng)論 5 346
  • 正文 年R本政府宣布减途,位于F島的核電站酣藻,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏鳍置。R本人自食惡果不足惜辽剧,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,249評(píng)論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望税产。 院中可真熱鬧怕轿,春花似錦、人聲如沸辟拷。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,866評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽衫冻。三九已至诀紊,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間隅俘,已是汗流浹背渡紫。 一陣腳步聲響...
    開封第一講書人閱讀 32,991評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留考赛,地道東北人惕澎。 一個(gè)月前我還...
    沈念sama閱讀 48,063評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像颜骤,于是被迫代替她去往敵國(guó)和親唧喉。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,871評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,126評(píng)論 25 707
  • ContentProvider 用戶跨進(jìn)程訪問數(shù)據(jù),通常和數(shù)據(jù)庫(kù)以及ContentResolver配合使用八孝,可以保...
    ACE_Killer09閱讀 1,728評(píng)論 0 2
  • 文/可君 臨窗冷雨暖寒春董朝,三月桃紅柳色新。 誰剪清風(fēng)迎嫁娶干跛,我攜紅日送鄉(xiāng)鄰子姜。 年年春曉醒多事,歲歲花眠少幾人楼入。 敢...
    草堂書翁閱讀 734評(píng)論 2 8
  • 最近因?yàn)橐褂肅harles抓數(shù)據(jù)哥捕,但是提示Java環(huán)境版本過高,導(dǎo)致Charles不能正常使用嘉熊。首先卸載新版本J...
    Anchoriter閱讀 1,965評(píng)論 0 49
  • 喵咪敏閱讀 133評(píng)論 0 0