Android四大組件--ContentProvider

一、簡(jiǎn)介

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

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

總的來(lái)說(shuō),利用ContentProvider來(lái)實(shí)現(xiàn)共享數(shù)據(jù)的好處是統(tǒng)一了數(shù)據(jù)的訪問(wèn)方式。

二、使用方法

ContentProvide的使用涉及ContentProvider、 ContentObserver、 ContentReslover 、ContentValues、Cursor、Uri、UriMatcher以及數(shù)據(jù)庫(kù)等。

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ù)庫(kù)或鏈接數(shù)據(jù)庫(kù),以及提供為contentResolver增刪改查的方法。

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

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

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

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

ContentResolver提供的操作方法:
insert、getType、delete、query、update等與ProvideContent相對(duì)應(yīng),通過(guò)Uri鏈接ContentProvide和ContentResolver

Cursor類,游標(biāo)。應(yīng)用時(shí)一般通過(guò)查詢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)用第一次訪問(wèn)它時(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/開(kāi)頭,如要得到所有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/開(kāi)頭,如得到id為10的tablename記錄,Uri為content://com.wang.provider.myprovider/tablename/10,那么返回的MIME類型字符串為:vnd.android.cursor.item/tablename 。

四、UriMatcher

Uri代表要操作的數(shù)據(jù),在開(kāi)發(fā)過(guò)程中對(duì)數(shù)據(jù)進(jìn)行獲取時(shí)需要解析Uri,Android提供了兩個(gè)用于操作Uri的工具類,分別為UriMatcher和ContentUris 。掌握它們的基本概念和使用方法,對(duì)一個(gè)Android開(kāi)發(fā)者來(lái)說(shuō)是一項(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 類來(lái)完成。而要獲取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)聽(tīng)數(shù)據(jù)變化

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

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

而訪問(wèn)者必須使用ContentObserver對(duì)數(shù)據(jù)(數(shù)據(jù)采用uri描述)進(jìn)行監(jiān)聽(tīng),當(dāng)監(jiān)聽(tīng)到數(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

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

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

相關(guān)閱讀更多精彩內(nèi)容

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