Android开发学习之四大组件之一 --- ContentProvider
【ContentProvider简介】
在Android中,每一个应用程序都是采用私有的形式进行操作的,不管这些数据是用文件还是数据库保存,都不能被外部应用程序所访问。但是在很多情况下,用户需要可以在不同的应用之间进行数据交换,为了解决这个问题,在Android中专门提供了一个ContentProvider类,此类的 主要功能是将不同的应用程序的操作标准统一起来,并且将各个应用程序的数据操作标准表明给其他的应用程序,这样,一个应用程序中的数据就可以按照ContentProvider所制定的标准被外部所操作
提示:ContentProvider的主要作用是在不同的应用程序之间进行数据交换,这类似于Web Services技术
简单地说:
- ContentProvider将应用中的数据对其它应用进行共享, 提供增删改查的方法
- ContentProvider统一了数据的访问方式,不必针对不同数据类型采取不同的访问策略
- ContentProvider将数据封装,只暴露出我们希望提供给其它程序的数据
- ContentProvider中可以注册观察者, 监听数据的变化
- 定义类继承ContentProvider, 实现抽象方法
- 在清单文件中注册:在清单文件的<application>节点下进行配置<provider>标签,标签中需要指定name和authorities属性 name:完整的类名。可以省略包名(manifest节点的package值), 注意:省略后的类名是以"."开头的。(类名首字母大写别忘了) authorities:是访问Provider时的路径,要唯一 (uri的一部分)
将应用安装在手机上即可,不用运行程序即即可让其他程序操作
【其他应用访问方式】
- 外部应用使用ContentResolver类对ContentProvider中的数据进行访问(CRUD操作)
- 获取解析器ContentResolver ContentResolver resolver = Context.getContentResolver(); 通过resolver.insert(), delete(), update(), query()方法访问Uri关联的ContentProvider
- URI代表要操作的数据,由scheme、authorites、path三部分组成 eg: content://com.jxn.provider/person/3 scheme | authorites | path
- schema:ContentProvider(内容提供者)访问协议,固定为:"content://"
- Authority(主机名或授权):定义了是哪个ContentProvider提供这些数据。 用于唯一标识ContentProvider,外 部调用者可以根据该标识来找到它,一般都为程序的“包.类”名称,但是要采用小写字母的形式
- path:访问的路径,一般为要操作的数据表的名称,根据操作的不同一般可以分为如下几况 ①访问全部数据:content://Authority/path. 例如,访问member表的全部数据: content://org.lxh.demo.membercontentprovider/member/ ②根据ID访问数据:content://Authority/path/ID 例如:访问member表中ID为3的数据:content://org.lxh.demo.membercontentprovider/member/3 ③访问某一条记录的某个字段:content://访问标识/表名称 /ID/列名称 例如:访问member表第3条记录name字段中的数据: content://org.lxh.demo.membercontentprovider/member/3/name
Android系统提供了两个用于操作Uri的工具类:UriMatcher 和 ContentUris
【UriMatcher】
- 第一步:把你需要匹配的Uri路径全部给注册上,如下:
- //常量UriMatcher.NO_MATCH表示不匹配任何路径的返回码
- UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);
- //如果match()方法匹配content://com.jxn.provider.personprovider/person路径,返回匹配码为1
- matcher.addURI("com.jxn.provider.personprovider", "person", 1);//添加需要匹配uri,如果匹配就会返回匹配码
- //如果match()方法匹配content://com.jxn.provider.personprovider/person/230路径,返回匹配码为2
- matcher.addURI("com.jxn.provider.personprovider", "person/#", 2);//#号为通配符
- 第二步:使用matcher.match(uri)方法对输入的Uri进行匹配,如果匹配成功就返回匹配码
- switch (matcher.match(Uri.parse("content://com.jxn.provider.personprovider/person/10"))) {
- case 1
- // 相应的业务操作
- break;
- case 2
- // 相应的业务操作
- break;
- default:
- // 相应的业务操作
- break;
- }
【ContentUris】
- 给Uri加上id: ContentUris.withAppendedId(uri, id)
- 获取id: ContentUris.parseId(uri)
【监听内容提供者数据变化】
- 如果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);
- // 注:如果没有调用notifyChange()方法,即使其它应用注册了ContentObserver,也不会知道ContentProvider中的数据的变化
- getContext().getContentResolver().notifyChange(uri, null);
- }
- }
- 2,如果ContentProvider的访问者需要得到数据变化通知,必须使用ContentObserver对数据(用uri描述)进行监听,当监听到数据变化通知时,系统就会调用ContentObserver的onChange()方法:
- getContentResolver().registerContentObserver(Uri.parse("content://com.jxn.providers.personprovider/person"),true, new PersonObserver(new Handler()));
- public class PersonObserver extends ContentObserver{
- public PersonObserver(Handler handler) {
- super(handler);
- }
- public void onChange(boolean selfChange) {
- //此处可以进行相应的业务处理
- }
- }
- getType()方法:主要用于匹配数据类型,返回当前Uri所代表数据的MIME类型。
- 如果返回数据是单条数据:vnd.android.cursor.item
- 如果返回数据是多条数据:vnd.android.cursor.dir