一烂瘫、簡(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ì)你也有幫助贪磺,榮幸之至。