contentprovider总结

转载博客:http://blog.csdn.net/yhaolpz/article/details/51304345

参考博客:http://blog.sina.com.cn/s/blog_9f233c070101euqx.html

ContentProvider调用关系:


ContentProvider(数据提供者)是应用程序之间共享数据的一种接口机制,是一种更为高级的数据共享方法。

  • ContentProvider可以指定需要共享的数据,而其他应用程序则可以在不知道数据来源、路径的情况下,对共享数据进行增删改查等操作。
  • 在Android系统中,许多Android系统内置的数据也是通过ContentProvider提供给用户使用,例如通讯录、音视频文件和图像文件等。

通用资源标识符(Uniform Resource Identifier)

URI是一个用于标识某一互联网资源名称的字符串。 该种标识允许用户对任何(包括本地和互联网)的资源通过特定的协议进行交互操作。在ContentProvider机制中,使用ContentResolver对象通过URI定位ContentProvider提供的资源。
ContentProvider使用的URI语法结构如下:

    content://<authority>/<data_path>/<id>

  • content:// 是通用前缀,表示该UIR用于ContentProvider定位资源。
  • < authority > 是授权者名称,用来确定具体由哪一个ContentProvider提供资源。因此一般< authority >都由类的小写全称组成,以保证唯一性。
  • < data_path > 是数据路径,用来确定请求的是哪个数据集。如果ContentProvider近提供一个数据集,数据路径则可以省略;如果ContentProvider提供多个数据集,数据路径必须指明具体数据集。数据集的数据路径可以写成多段格式,例如people/girl和people/boy。
  • < id > 是数据编号,用来唯一确定数据集中的一条记录,匹配数据集中_ID字段的值。如果请求的数据不只一条,< id >可以省略。

如请求整个people数据集的URI为:

content://com.example.peopleprovider/people
而请求people数据集中第3条数据的URI则应写为:

content://com.example.peopleprovider/people/3

创建数据提供者

1. 创建一个类让其继承ContentProvider,并重载6个函数

  • onCreate()
    一般用来初始化底层数据集和建立数据连接等工作

  • getType()
    用来返回指定URI的MIME数据类型,若URI是单条数据,则返回的MIME数据类型以vnd.android.cursor.item开头;若URI是多条数据,则返回的MIME数据类型以vnd.android.cursor.dir/开头。

  • insert()、delete()、update()、query()
    用于对数据集的增删改查操作。

2. 声明CONTENT_URI,实现UriMatcher

public static final String AUTHORITY = "com.example.peopleprovider";
public static final String PATH_SINGLE = "people/#";
public static final String PATH_MULTIPLE = "people";
public static final String CONTENT_URI_STRING = "content://" + AUTHORITY + "/" + PATH_MULTIPLE;
public static final Uri CONTENT_URI = Uri.parse(CONTENT_URI_STRING);
public static final int MULTIPLE_PEOPLE = 1;
public static final int SINGLE_PEOPLE = 2;
public static final UriMatcher uriMatcher;
static{
      uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
      uriMatcher.addURI(AUTHORITY, PATH_SINGLE, SINGLE_PEOPLE );
      uriMatcher.addURI(AUTHORITY, PATH_MULTIPLE , MULTIPLE_PEOPLE );
}

其中UriMatcher类引用官方文档中的解释:

      Utility class to aid in matching URIs in content providers.

可见UriMatcher本质上是一个文本过滤器,用在contentProvider中帮助我们过滤,分辨出查询者想要查询哪个数据表。
UriMatcher的构造函数中,UriMatcher.NO_MATCH是URI无匹配时的返回代码,值为-1。 addURI() 方法用来添加新的匹配项,语法为:

public void addURI(String authority, String path, int code)
其中 authority表示匹配的授权者名称, path表示数据路径(#代表任何数字), code表示返回代码。

关于UriMatcher的使用

switch(uriMatcher.match(uri)){
    case MULTIPLE_PEOPLE:
         //多条数据的处理
         break;
    case SINGLE_PEOPLE:
         //单条数据的处理
         break;
    default:
         throw new IllegalArgumentException("不支持的URI:" + uri);
}

3. 注册ContentProvider

在AndroidManifest.xml文件中的 application节点下使用< provider >标签注册。示例:

<provider
            android:authorities="com.example.peopleprovider"
            android:name=".Peopleprovider" />

使用数据提供者

每个Android组件都有一个ContentResolver对象,通过调用getContentResolver() 方法可得到ContentResolver对象。
准备工作:
ContentResolver resolver = getContentResolver();
String KEY_ID = "_id";
String KEY_NAME = "name";
String KEY_AGE = "age";
String KEY_HEIGHT = "height";

1. 添加操作

通过insert()函数添加单条数据
(returns : the URL of the newly created row.)

  ContentValues values = new ContentValues();
    values.put(KEY_NAME, "Tom");
    values.put(KEY_AGE, 21);
    values.put(KEY_HEIGHT, 1.81f);
    Uri newUri = resolver.insert(CONTENT_URI, values);
通过bulkInsert()函数添加 多条数据
(returns:the number of newly created rows.)

ContentValues[] arrayValues = new ContentValues[10];
//实例化每一个ContentValues...
int count = resolver.bulkInsert(CONTENT_URI, arrayValues );

2. 删除操作

指定ID删除单条数据

Uri uri = Uri.parse(CONTENT_URI_STRING + "/" +"2");
int result = resolver.delete(uri, null, null);

通过selection语句删除 多条数据

String selection = KEY_ID + ">4";
int result = resolver.delete(CONTENT_URI, selection, null);

3. 更新操作

    ContentValues values = new ContentValues();
    values.put(KEY_NAME, "Tom");
    values.put(KEY_AGE, 21);
    values.put(KEY_HEIGHT, 1.81f);
    Uri rui = Uri.parse(CONTENT_URI_STRING + "/" + "7");
    int result = resolver.update(uri, values, null, null);

4. 查询操作

Uri uri = Uri.parse(CONTENT_URI_STRING + "/" + "2");
Cursor cursor = resolver.query(uri, new String[]{KEY_ID, KEY_NAME, KEY_AGE, KEY_HEIGHT}, null, null, null);

在URI中定义了需要查询数据的ID后,在query()函数中没有必要再加入其他的查询条件,如果要获取数据集全部数据,则可以直接使用CONTENT_URI且不加查询条件。
在Android系统中,数据库查询结果的返回值并不是数据集合的完整拷贝,而是返回数据集的指针,这个指针就是Cursor类。ContentProvider的数据集类似数据库的数据表,其查询结果的返回值同样是数据集的指针:Cursor类。在提取Cursor数据中的数据前,推荐测试Cursor中的数据数量,避免在数据获取中产生异常。示例如下:

public people[] getPeople(Cursor cursor){
    int resultCounts = cursor.getCount();
    if(resultCounts == 0 !cursor.moveToFirst()){
        return null;
    }
    People[] peoples = new People[resultCounts];
    for(int i=0; i<resultCounts; i++){
        peoples[i] = new People();
        peoples[i].ID = cursor.getInt(0);
        peoples[i].Name = cursor.getString(cursor.getColumnIndex(KEY_NAME));
        peoples[i].Age = cursor.getInt(cursor.getColumnIndex(KEY_AGE));
        peoples[i].Height= cursor.getFloat(cursor.getColumnIndex(KEY_HEIGHT));
        cursor.moveToNext();
    }
    return peoples;
}


其他:

1.ContentUris类使用介绍

ContentUris类用于操作Uri路径后面的ID部分,它有两个比较实用的方法:
withAppendedId(uri, id)
用于为路径加上ID部分:

Uri uri = Uri.parse("content://com.ljq.provider.personprovider/person")

Uri resultUri = ContentUris.withAppendedId(uri, 10); 
//生成后的Uri为:content://com.ljq.provider.personprovider/person/10


parseId(uri)方法用于从路径中获取ID部分:

Uri uri = Uri.parse("content://com.ljq.provider.personprovider/person/10")
long personid = ContentUris.parseId(uri);//获取的结果为:10


2.监听ContentProvider中数据的变化


如果ContentProvider的访问者需要知道ContentProvider中的数据发生变化,可以在ContentProvider发生数据变化时调用getContentResolver().notifyChange(uri,null)来通知注册在此URI上的访问者,例子如下:

public class PersonContentProvider extends ContentProvider {
   public Uri insert(Uri uri, ContentValues values) {
      db.insert("person", "personid", values);
      getContext().getContentResolver().notifyChange(uri, null);
   }
} 

如果ContentProvider的访问者需要得到数据变化通知,必须使用ContentObserver对数据(数据采用uri描述)进行监听,当监听到数据变化通知时,系统就会调用ContentObserveronChange()方法:

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) {
      //此处可以进行相应的业务处理
   }
} 

3.权限设置与线程同步

1.     可以在代码中通过setReadPermission()和setWritePermission()两个方法来设置ContentProvider的操作权限,也可以在配置文件中通过android:readPermission和android:writePermission属性来控制。

2.     因为ContentProvider可能被不同的进程和线程调用,所以里面的方法必须是线程安全的。








  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值