Android学习笔记之ContentProvider和Uri详解
本文介绍了自定义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) { //此处可以进行相应的业务处理 } }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
推荐阅读
-
Android学习笔记之ContentProvider和Uri详解
-
Android学习笔记之ContentProvider和Uri详解
-
[Android] ContentProvider和Uri详解
-
Android学习笔记(Android Studio) 4-2-1~2 Fragment详解(一、二)(不可不会的Activity和Fragment)
-
JS学习笔记之原型链和利用原型实现继承详解
-
Android学习笔记之ListView复用机制详解
-
JS学习笔记之原型链和利用原型实现继承详解
-
Android学习笔记之ListView复用机制详解
-
Android学习笔记之AndroidManifest.xml文件解析(详解)
-
Android学习笔记之AndroidManifest.xml文件解析(详解)