Android四大組件--ContentProvider

一烂瘫、簡(jiǎn)介

ContentProvider是Android四大組件之一的內(nèi)容提供器

ContentProvider為存儲(chǔ)和獲取數(shù)據(jù)提供了統(tǒng)一的接口胳施,使用表的形式來對(duì)數(shù)據(jù)進(jìn)行封裝,使得開發(fā)者在后續(xù)的開發(fā)過程中不用關(guān)心數(shù)據(jù)存儲(chǔ)的細(xì)節(jié)捂贿。使用ContentProvider可以在不同的應(yīng)用程序之間共享數(shù)據(jù)纠修,Android為常見的數(shù)據(jù)類型提供了默認(rèn)的ContentProvider(包括音頻、視頻厂僧、圖片和通訊錄等)。

總的來說了牛,利用ContentProvider來實(shí)現(xiàn)共享數(shù)據(jù)的好處是統(tǒng)一了數(shù)據(jù)的訪問方式颜屠。

二辰妙、使用方法

ContentProvide的使用涉及ContentProvider、 ContentObserver甫窟、 ContentReslover 密浑、ContentValues、Cursor粗井、Uri尔破、UriMatcher以及數(shù)據(jù)庫等。

ContentProvider,它最大的特點(diǎn)是可以在應(yīng)用之間共享數(shù)據(jù)

1.定義自己的ContentProvide類浇衬,

2.在AndroidManifest.xml上注冊(cè)懒构,并指定authorities屬性,給外界提供固定Uri對(duì)外提供服務(wù)

  • 提供的方法

操作方法:insert耘擂、getType胆剧、delete、query醉冤、update秩霍、oncreate用于創(chuàng)建數(shù)據(jù)庫或鏈接數(shù)據(jù)庫,以及提供為contentResolver增刪改查的方法蚁阳。

ContentValues是用于存儲(chǔ)ContentResolver處理的值铃绒。

ContentResolver用于訪問content模型,其實(shí)就是訪問和操作contentprovider螺捐。

  • 實(shí)現(xiàn)方式

Context提供了getContentResolver方法颠悬,這表明Activity、Service組件都可通過該方法獲取該類的實(shí)例

ContentResolver提供的操作方法:
insert归粉、getType椿疗、delete、query糠悼、update等與ProvideContent相對(duì)應(yīng)届榄,通過Uri鏈接ContentProvide和ContentResolver

Cursor類,游標(biāo)倔喂。應(yīng)用時(shí)一般通過查詢query得到铝条。

Uri:協(xié)議部分、域名席噩、路徑班缰、ID、字段

其中協(xié)議部分:content://
域名對(duì)應(yīng)authoties屬性

路徑:資源部分或數(shù)據(jù)部分

三悼枢、ContentProvider類主要方法的介紹:
  • public boolean onCreate()埠忘,在ContentProvider創(chuàng)建后就會(huì)被調(diào)用,而ContentProvider是在其它應(yīng)用第一次訪問它時(shí)被創(chuàng)建;

  • public Uri insert(Uri uri, ContentValues values)莹妒,供外部應(yīng)用向ContentProvider添加數(shù)據(jù)名船;

  • public int delete(Uri uri, String selection, String[] selectionArgs),供外部應(yīng)用從ContentProvider刪除數(shù)據(jù)旨怠;

  • public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs)渠驼,供外部應(yīng)用更新ContentProvider中的數(shù)據(jù);

  • public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)鉴腻,供外部應(yīng)用從ContentProvider中獲取數(shù)據(jù)迷扇;

  • public String getType(Uri uri),返回當(dāng)前Uri所代表數(shù)據(jù)的MIME類型爽哎;

如果操作的數(shù)據(jù)屬于集合類型蜓席,那么MIME類型字符串應(yīng)該以vnd.android.cursor.dir/開頭,如要得到所有tablename記錄的Uri為content://com.wang.provider.myprovider/tablename倦青,那么返回的MIME類型字符串應(yīng)該為:vnd.android.cursor.dir/table瓮床。

如果要操作的數(shù)據(jù)屬于非集合類型數(shù)據(jù),那么MIME類型字符串應(yīng)該以vnd.android.cursor.item/開頭产镐,如得到id為10的tablename記錄隘庄,Uri為content://com.wang.provider.myprovider/tablename/10,那么返回的MIME類型字符串為:vnd.android.cursor.item/tablename 癣亚。

四丑掺、UriMatcher

Uri代表要操作的數(shù)據(jù),在開發(fā)過程中對(duì)數(shù)據(jù)進(jìn)行獲取時(shí)需要解析Uri述雾,Android提供了兩個(gè)用于操作Uri的工具類街州,分別為UriMatcher和ContentUris 。掌握它們的基本概念和使用方法玻孟,對(duì)一個(gè)Android開發(fā)者來說是一項(xiàng)必要的技能唆缴。

1、UriMatcher

UriMatcher類用于匹配Uri黍翎,它的使用步驟如下:

  • a面徽、將需要匹配的Uri路徑進(jìn)行注冊(cè),代碼如下:
1 //常量UriMatcher.NO_MATCH表示不匹配任何路徑的返回碼
2 UriMatcher  sMatcher = new UriMatcher(UriMatcher.NO_MATCH);
3 //如果match()方法匹配“content://com.wang.provider.myprovider/tablename”路徑匣掸,返回匹配碼為1
4 sMatcher.addURI("content://com.wang.provider.myprovider", " tablename ", 1);
5  //如果match()方法匹配content://com.wang.provider.myprovider/tablename/11路徑趟紊,返回匹配碼為2
6 sMatcher.addURI("com.wang.provider.myprovider", "tablename/#", 2);

注意:添加第二個(gè)URI時(shí),路徑后面的id采用了通配符形式“#”碰酝,表示只要前面三個(gè)部分都匹配上了就OK霎匈。

  • b、注冊(cè)完需要匹配的Uri后送爸,可以使用sMatcher.match(Uri)方法對(duì)輸入的Uri進(jìn)行匹配铛嘱,如果匹配就返回對(duì)應(yīng)的匹配碼暖释,匹配碼為調(diào)用addURI()方法時(shí)傳入的第三個(gè)參數(shù)。
 switch (sMatcher.match(Uri.parse("content://com.zhang.provider.yourprovider/tablename/100"))) {
     case 1:
       //match 1, todo something
       break;
     case 2
       //match 2, todo something
       break;
     default:
       //match nothing, todo something
      break;
 }
2弄痹、ContentUris

ContentUris類用于操作Uri路徑后面的ID部分饭入,它有兩個(gè)比較實(shí)用的方法:

withAppendedId(Uri uri, long id)和parseId(Uri uri)嵌器。

withAppendedId(Uri uri, long id)用于為路徑加上ID部分:

 Uri uri = Uri.parse("content://com.wang.provider.myprovider/tablename");
 
 Uri resultUri = ContentUris.withAppendedId(uri, 10);

parseId(Uri uri)則從路徑中獲取ID部分:

Uri uri = Uri.parse("content://com.zhang.provider.myprovider/tablename/10");

long personid = ContentUris.parseId(uri);

五肛真、ContentResolver操作數(shù)據(jù)

當(dāng)外部應(yīng)用需要對(duì)ContentProvider中的數(shù)據(jù)進(jìn)行添加、刪除爽航、修改及查詢操作時(shí)蚓让,可以使用ContentResolver 類來完成。而要獲取ContentResolver 對(duì)象讥珍,可以使用Activity提供的getContentResolver()方法历极。

ContentResolver 類提供了與ContentProvider類相同簽名的四個(gè)方法:

  • public Uri insert(Uri uri, ContentValues values),往ContentProvider添加數(shù)據(jù)衷佃;

  • public int delete(Uri uri, String selection, String[] selectionArgs)趟卸,從ContentProvider刪除數(shù)據(jù);

  • public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs)氏义,更新ContentProvider中的數(shù)據(jù)锄列;

  • public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder),從ContentProvider中獲取數(shù)據(jù)惯悠;

這些方法的第一個(gè)參數(shù)為Uri邻邮,代表要操作的ContentProvider和對(duì)其中的什么數(shù)據(jù)進(jìn)行操作,其實(shí)和ContentProvider里面的方法是一樣的克婶。他們所對(duì)應(yīng)的數(shù)據(jù)筒严,最終會(huì)被傳到我們?cè)谥俺绦蚶锩娑x的那個(gè)ContentProvider類的方法,假設(shè)給定的是:Uri.parse("content://com.wang.provider.myprovider/tablename/10")情萤,那么將會(huì)對(duì)主機(jī)名為com.wang.provider.myprovider的ContentProvider進(jìn)行操作鸭蛙,操作的數(shù)據(jù)為tablename表中id為10的記錄。

使用ContentResolver對(duì)ContentProvider中的數(shù)據(jù)進(jìn)行操作的代碼如下:

  ContentResolver resolver = getContentResolver();
  
  Uri uri = Uri.parse("content://com.wang.provider.myprovider/tablename");
  
  //添加一條記錄
  ContentValues values = new ContentValues();
  values.put("name", "wang1");
  values.put("age", 28);
  resolver.insert(uri, values); 
  
  //獲取tablename表中所有記錄
  Cursor cursor = resolver.query(uri, null, null, null, "tablename data");
  
  while(cursor.moveToNext()){
    Log.i("ContentTest", "tablename_id="+ cursor.getInt(0)+ ", name="+ cursor.getString(1));
    }
 
  //把id為1的記錄的name字段值更改新為zhang1
  ContentValues updateValues = new ContentValues();
  
  updateValues.put("name", "zhang1");
  Uri updateIdUri = ContentUris.withAppendedId(uri, 2);
  
  resolver.update(updateIdUri, updateValues, null, null);
  
  //刪除id為2的記錄筋岛,即字段age
  Uri deleteIdUri = ContentUris.withAppendedId(uri, 2);
  
  resolver.delete(deleteIdUri, null, null);

六娶视、監(jiān)聽數(shù)據(jù)變化

如果ContentProvider的訪問者需要知道數(shù)據(jù)發(fā)生的變化,可以在ContentProvider發(fā)生數(shù)據(jù)變化時(shí)調(diào)用getContentResolver().notifyChange(uri, null)來通知注冊(cè)在此URI上的訪問者泉蝌。只給出類中監(jiān)聽部分的代碼:

 public class MyProvider extends ContentProvider {
   public Uri insert(Uri uri, ContentValues values) {
       db.insert("tablename", "tablenameid", values);
       getContext().getContentResolver().notifyChange(uri, null);
    }
 }

而訪問者必須使用ContentObserver對(duì)數(shù)據(jù)(數(shù)據(jù)采用uri描述)進(jìn)行監(jiān)聽歇万,當(dāng)監(jiān)聽到數(shù)據(jù)變化通知時(shí),系統(tǒng)就會(huì)調(diào)用ContentObserver的onChange()方法:

  getContentResolver().registerContentObserver(Uri.parse("content://com.ljq.providers.personprovider/person"),
         true, new PersonObserver(new Handler()));
  public class PersonObserver extends ContentObserver{
     public PersonObserver(Handler handler) {
        super(handler);
     }
    public void onChange(boolean selfChange) {
        //to do something
     }
 }

參考學(xué)習(xí):https://www.cnblogs.com/tgyf/p/4696288.html

寫在最后: 本系列的文章旨在學(xué)習(xí)過程中的總結(jié)勋陪,如果對(duì)你也有幫助贪磺,榮幸之至。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末诅愚,一起剝皮案震驚了整個(gè)濱河市寒锚,隨后出現(xiàn)的幾起案子劫映,更是在濱河造成了極大的恐慌,老刑警劉巖刹前,帶你破解...
    沈念sama閱讀 207,248評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件泳赋,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡喇喉,警方通過查閱死者的電腦和手機(jī)祖今,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來拣技,“玉大人千诬,你說我怎么就攤上這事「嘟铮” “怎么了徐绑?”我有些...
    開封第一講書人閱讀 153,443評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)莫辨。 經(jīng)常有香客問我傲茄,道長(zhǎng),這世上最難降的妖魔是什么沮榜? 我笑而不...
    開封第一講書人閱讀 55,475評(píng)論 1 279
  • 正文 為了忘掉前任盘榨,我火速辦了婚禮,結(jié)果婚禮上敞映,老公的妹妹穿的比我還像新娘较曼。我一直安慰自己,他們只是感情好振愿,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,458評(píng)論 5 374
  • 文/花漫 我一把揭開白布捷犹。 她就那樣靜靜地躺著,像睡著了一般冕末。 火紅的嫁衣襯著肌膚如雪萍歉。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,185評(píng)論 1 284
  • 那天档桃,我揣著相機(jī)與錄音枪孩,去河邊找鬼。 笑死藻肄,一個(gè)胖子當(dāng)著我的面吹牛蔑舞,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播嘹屯,決...
    沈念sama閱讀 38,451評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼攻询,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了州弟?” 一聲冷哼從身側(cè)響起钧栖,我...
    開封第一講書人閱讀 37,112評(píng)論 0 261
  • 序言:老撾萬榮一對(duì)情侶失蹤低零,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后拯杠,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體掏婶,經(jīng)...
    沈念sama閱讀 43,609評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,083評(píng)論 2 325
  • 正文 我和宋清朗相戀三年潭陪,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了雄妥。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,163評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡畔咧,死狀恐怖茎芭,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情誓沸,我是刑警寧澤,帶...
    沈念sama閱讀 33,803評(píng)論 4 323
  • 正文 年R本政府宣布壹粟,位于F島的核電站拜隧,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏趁仙。R本人自食惡果不足惜洪添,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,357評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望雀费。 院中可真熱鬧干奢,春花似錦、人聲如沸盏袄。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,357評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽辕羽。三九已至逛尚,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間刁愿,已是汗流浹背绰寞。 一陣腳步聲響...
    開封第一講書人閱讀 31,590評(píng)論 1 261
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留铣口,地道東北人滤钱。 一個(gè)月前我還...
    沈念sama閱讀 45,636評(píng)論 2 355
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像脑题,于是被迫代替她去往敵國和親件缸。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,925評(píng)論 2 344

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