当前位置: 移动技术网 > IT编程>移动开发>Android > Android学习笔记之ContentProvider和Uri详解

Android学习笔记之ContentProvider和Uri详解

2019年07月24日  | 移动技术网IT编程  | 我要评论

淄博晚报,北京林业大学登天,重庆天涯论坛首页

本文介绍了自定义content provider的相关内容,完全解析内容提供者的用法。content provider,内容提供者,相信大家对这个组件的名字都不陌生,可能是自己平时做的都是一些简单的app,所以对于content provider的使用并不是很多,也不是特别熟悉。但是这里还是对content provider作个简单的总结,不是很深入,但是希望能给包括我在内的初学者一点帮助,看完这篇能对这个组件有个总体上的了解。

一、使用contentprovider(内容提供者)共享数据

contentprovider在android中的作用是对外共享数据,也就是说你可以通过contentprovider把应用中的数据共享给其他应用访问,其他应用可以通过contentprovider对你应用中的数据进行添删改查。关于数据共享,以前我们学习过文件操作模式,知道通过指定文件的操作模式为context.mode_world_readable或context.mode_world_writeable同样也可以对外共享数据。那么,这里为何要使用contentprovider对外共享数据呢?是这样的,如果采用文件操作模式对外共享数据,数据的访问方式会因数据存储的方式而不同,导致数据的访问方式无法统一,如:采用xml文件对外共享数据,需要进行xml解析才能读取数据;采用sharedpreferences共享数据,需要使用sharedpreferences api读取数据。使用contentprovider对外共享数据的好处是统一了数据的访问方式。当应用需要通过contentprovider对外共享数据时,第一步需要继承contentprovider并重写下面方法:   

public class personcontentprovider extends contentprovider{ 
  public boolean oncreate() 
  public uri insert(uri uri, contentvalues values) 
  public int delete(uri uri, string selection, string[] selectionargs) 
  public int update(uri uri, contentvalues values, string selection, string[] selectionargs) 
  public cursor query(uri uri, string[] projection, string selection, string[] selectionargs, string sortorder) 
  public string gettype(uri uri) 
} 

    第二步需要在androidmanifest.xml使用<provider>对该contentprovider进行配置,为了能让其他应用找到该contentprovider ,contentprovider采用了authorities(主机名/域名)对它进行唯一标识,你可以把contentprovider看作是一个网站(想想,网站也是提供数据者),authorities 就是他的域名:
 

  <manifest.... > 
 <application android:icon="@drawable/icon" android:label="@string/app_name"> 
   <provider android:name=".personcontentprovider"  
   android:authorities="com.ljq.providers.personprovider"/> 
 </application> 
</manifest> 

二、uri介绍
uri代表了要操作的数据,uri主要包含了两部分信息:1》需要操作的contentprovider ,2》对contentprovider中的什么数据进行操作,一个uri由以下几部分组成:

contentprovider(内容提供者)的scheme已经由android所规定, scheme为:content://

主机名(或叫authority)用于唯一标识这个contentprovider,外部调用者可以根据这个标识来找到它。

路径(path)可以用来表示我们要操作的数据,路径的构建应根据业务而定,如下:

要操作person表中id为10的记录,可以构建这样的路径:/person/10

要操作person表中id为10的记录的name字段, person/10/name

要操作person表中的所有记录,可以构建这样的路径:/person

要操作xxx表中的记录,可以构建这样的路径:/xxx

当然要操作的数据不一定来自数据库,也可以是文件、xml或网络等其他存储方式,如下:

要操作xml文件中person节点下的name节点,可以构建这样的路径:/person/name

如果要把一个字符串转换成uri,可以使用uri类中的parse()方法,如下:

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

三、urimatcher类使用介绍

因为uri代表了要操作的数据,所以我们经常需要解析uri,并从uri中获取数据。android系统提供了两个用于操作uri的工具类,分别为urimatcher和contenturis 。掌握它们的使用,会便于我们的开发工作。
urimatcher类用于匹配uri,它的用法如下:

首先第一步把你需要匹配uri路径全部给注册上,如下:

//常量urimatcher.no_match表示不匹配任何路径的返回码 
urimatcher smatcher = new urimatcher(urimatcher.no_match); 
//如果match()方法匹配content://com.ljq.provider.personprovider/person路径,返回匹配码为1 
smatcher.adduri("com.ljq.provider.personprovider", "person", 1);//添加需要匹配uri,如果匹配就会返回匹配码 
//如果match()方法匹配content://com.ljq.provider.personprovider/person/230路径,返回匹配码为2 
smatcher.adduri("com.ljq.provider.personprovider", "person/#", 2);//#号为通配符 
switch (smatcher.match(uri.parse("content://com.ljq.provider.personprovider/person/10"))) { 
  case 1 
   break; 
  case 2 
   break; 
  default://不匹配 
   break; 
} 

注册完需要匹配的uri后,就可以使用smatcher.match(uri)方法对输入的uri进行匹配,如果匹配就返回匹配码,匹配码是调用adduri()方法传入的第三个参数,假设匹配content://com.ljq.provider.personprovider/person路径,返回的匹配码为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 

五、使用contentprovider共享数据

contentprovider类主要方法的作用:

public boolean oncreate() 
该方法在contentprovider创建后就会被调用,android开机后,contentprovider在其它应用第一次访问它时才会被创建。

public uri insert(uri uri, contentvalues values)
该方法用于供外部应用往contentprovider添加数据。

public int delete(uri uri, string selection, string[] selectionargs)
该方法用于供外部应用从contentprovider删除数据。

public int update(uri uri, contentvalues values, string selection, string[] selectionargs)
该方法用于供外部应用更新contentprovider中的数据。

public cursor query(uri uri, string[] projection, string selection, string[] selectionargs, string sortorder)
该方法用于供外部应用从contentprovider中获取数据。

public string gettype(uri uri)
该方法用于返回当前url所代表数据的mime类型。如果操作的数据属于集合类型,那么mime类型字符串应该以vnd.android.cursor.dir/开头,

 例如:要得到所有person记录的uri为content://com.ljq.provider.personprovider/person,那么返回的mime类型字符串应该为:"vnd.android.cursor.dir/person"。

如果要操作的数据属于非集合类型数据,那么mime类型字符串应该以vnd.android.cursor.item/开头,

例如:得到id为10的person记录,uri为content://com.ljq.provider.personprovider/person/10,那么返回的mime类型字符串为:"vnd.android.cursor.item/person"。

六、使用contentresolver操作contentprovider中的数据

当外部应用需要对contentprovider中的数据进行添加、删除、修改和查询操作时,可以使用contentresolver 类来完成,要获取contentresolver 对象,可以使用activity提供的getcontentresolver()方法。 contentresolver 类提供了与contentprovider类相同签名的四个方法:

public uri insert(uri uri, contentvalues values)
该方法用于往contentprovider添加数据。

public int delete(uri uri, string selection, string[] selectionargs)
该方法用于从contentprovider删除数据。

public int update(uri uri, contentvalues values, string selection, string[] selectionargs)
该方法用于更新contentprovider中的数据。

public cursor query(uri uri, string[] projection, string selection, string[] selectionargs, string sortorder)
该方法用于从contentprovider中获取数据。

这些方法的第一个参数为uri,代表要操作的contentprovider和对其中的什么数据进行操作,
假设给定的是:uri.parse("content://com.ljq.providers.personprovider/person/10"),那么将会对主机名为com.ljq.providers.personprovider的contentprovider进行操作,操作的数据为person表中id为10的记录。
使用contentresolver对contentprovider中的数据进行添加、删除、修改和查询操作:

contentresolver resolver = getcontentresolver(); 
uri uri = uri.parse("content://com.ljq.provider.personprovider/person"); 
//添加一条记录 
contentvalues values = new contentvalues(); 
values.put("name", "linjiqin"); 
values.put("age", 25); 
resolver.insert(uri, values);  
//获取person表中所有记录 
cursor cursor = resolver.query(uri, null, null, null, "personid desc"); 
while(cursor.movetonext()){ 
  log.i("contenttest", "personid="+ cursor.getint(0)+ ",name="+ cursor.getstring(1)); 
} 
//把id为1的记录的name字段值更改新为zhangsan 
contentvalues updatevalues = new contentvalues(); 
updatevalues.put("name", "zhangsan"); 
uri updateiduri = contenturis.withappendedid(uri, 2); 
resolver.update(updateiduri, updatevalues, null, null); 
//删除id为2的记录 
uri deleteiduri = contenturis.withappendedid(uri, 2); 
resolver.delete(deleteiduri, null, null); 

七、监听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描述)进行监听,当监听到数据变化通知时,系统就会调用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) { 
   //此处可以进行相应的业务处理 
  } 
} 

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持移动技术网。

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网