Android四大组件总结——ContentProvider
ContentProvider是Android四大组件之一,主要用于在不同应用间实现数据共享的功能。是Android实现跨程序共享数据的标准方式。
ContentProvider的基本使用
ContentProvider一般有两种用法,一种是用现有的ContentProvider来读取与操作相应程序的数据。另一种是创建自己的ContentProvider给程序的数据提供外部访问的接口。如果一个程序通过ContentProvider对它的数据提供了外部访问接口,则任何其他程序都可以对此部分数据进行访问。
读取数据:ContentResolver的使用
要访问ContentProvider中共享的内容,一般都会用到ContentResolver类。可以通过Context的getContentResolver()方法来获取该类的实例。其中提供了一系列方法来对数据进行增删查改。
与SQLite不同的是,ContentProvider的增删查改并不是接收表名参数,而是用内容URI。
内容URI
内容URI主要由两部分组成,authority与path。比如一个包名为com.android.test的app,它的authority就可以命名为com.android.test.provider。path是对一个应用程序不同的表做区分的,通常添加到authority的后面。如某个程序数据库中有两个表table1和table2,这时path就可以是/table1或者/table2。authority与path组合后,在头部加上协议声明后,就是一个标准的内容URI了。如:
content://com.android.test.provider/table1*
*content://com.android.test.provider/table2
得到内容URI字符串后,通过Uri类的parse方法即可将其解析为Uri对象了。
Uri uri = Uri.parse("content://com.android.test.provider/table1");
如果要访问的是table表中id为1的数据,可以通过uri后加上/id来实现。如:
Uri uri = Uri.parse("content://com.android.test.provider/table1/1");
Uri中还有两种通配符:
- *****:表示匹配任意长度的任意字符。
- #:表示匹配任意长度的数字。
我们可以用它们来达成查询任意表或某张表任意一条数据的效果
表示匹配任意表的内容的Uri:content://com.android.test.provider/*
表示table1表中任意一行的内容的Uri:content://com.android.test.provider/table1/#
查询数据
有了Uri后,我们只需要用它来进行查询就好了。查询后返回的是一个Cursor对象,然后我们就可以将数据从Cursor中逐个取出了。
Cursor cursor = getContentResolver().query(
uri,
projection,
selection,
selectionArgs,
sortOrder);
这些参数和SQLite中的参数有点相似。用SQL语句来举例的话,它们都有各自对应的部分
参数名 | 对应SQL部分 |
---|---|
uri | from table_name |
projection | select column1, column2 |
selection | where column = value |
selectionArgs | - |
sortOrder | order by column1, column2 |
添加数据
添加数据就很简单了,构造一个ContentValues,然后用insert方法将它插入就好。
ContentValues values = new ContentValues();
values.put("column1","text");
values.put("column2",1);
getContentResolver().insert(uri,values);
更新数据
更新数据也是非常简单的
ContentValues values = new ContentValues();
values.put("column1","");
getContentResolver().update(uri,values,"column1 = ? and column2 = ?", new String[]{
"text","1"});
删除数据
一样很简单
getContentResolver().update(uri,"column2 = ?",new String[]{"1"});
提供数据:ContentProvider的创建
如果想要在自己的应用中为外部提供接口来达到共享数据的目的,可以新建一个类继承ContentProvider,并重写它的六个抽象方法
- onCreate:初始化ContentProvider的时候调用,通常在这里进行数据库的创建和升级。返回true表示ContentProvider初始化成功,返回false则表示失败。
- query:从ContentProvider中查询数据,查询的结果存放在Cursor中返回。
- insert:向ContentProvider添加一条数据,返回用于表示这条新纪录的Uri。
- update:更新ContentProvider已有的数据,返回受影响的行数。
- delete:从ContentProvider中删除不数据。返回被删除的行数。
- getType:根据传入的Uri返回相应的MIME类型。
UriMatcher
我们可借助UriMatcher来轻松实现匹配内容Uri的功能。它提供了addURI方法,可分别把authority、path以及一个自定义代码传进去。这样,调用UriMatcher的match()方法时,就能传入一个Uri对象,返回匹配这个对象的自定义代码了。利用这个代码,我们就可以判断调用方希望访问哪张表的数据了。
public static final int TABLE1_DIR = 0;
public static final int TABLE1_ITEM = 1;
public static final int TABLE2_DIR = 2;
public static final int TABLE2_ITEM = 3;
public static UriMatcher uriMatcher;
static{
uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
uriMatcher.addURI("com.example.app.provider","table1",TABLE1_DIR);
uriMatcher.addURI("com.example.app.provider","table1/#",TABLE1_ITEM);
uriMatcher.addURI("com.example.app.provider","table2",TABLE2_DIR);
uriMatcher.addURI("com.example.app.provider","table2/#",TABLE2_ITEM);
}
实现增删查改方法
比如,我们可以用如下的方法来实现query方法:
@Override
public Cursor query(Uri uri,String[] projection,String selection,String[] selectionArgs,String sortOrder){
switch(uriMatcher.match(uri)){
case TABLE1_DIR:
//查询table1表的所有数据
break;
case TABLE1_ITEM:
//查询table1表的单条数据
break;
case TABLE2_DIR:
//查询table2表的所有数据
break;
case TABLE2_ITEM:
//查询table2表的单条数据
break;
...
}
...
}
除此之外,insert, update, delete这几个方法的实现也是差不多的。
实现getType方法
除增删查改方法外有一个方法需要注意,就是getType方法。它是所有ContentProvider都需要提供的方法,用于获取Uri对象对应的MIME类型。
MIME类型
一个内容URI所对应的MIME字符串主要由三部分组成:
- 必须以vnd开头
- 如果内容URI以path结尾,则后接android.cursor.dir/ ,如果以id结尾,则后接android.cursor.item/
- 最后接上vnd..
因此对于content://com.android.test.provider/table1这个内容Uri,它对应的MIME类型可以写成:
vnd.android.cursor.dir/vnd.com.android.test.provider.table1
对于content://com.android.test.provider/table1/1这个内容Uri,对应的MIME类型就可以写成:
vnd.android.cursor.item/vnd.com.android.test.provider.table1
实现getType方法
有了MIME类型的概念后,我们可以这样实现getType方法:
@Override
public String getType(Uri uri){
switch(uriMatcher.match(uri)){
case TABLE1_DIR:
return "vnd.android.cursor.dir/vnd.com.android.test.provider.table1";
case TABLE1_ITEM:
return "vnd.android.cursor.item/vnd.com.android.test.provider.table1";
case TABLE2_DIR:
return "vnd.android.cursor.dir/vnd.com.android.test.provider.table2";
case TABLE1_ITEM:
return "vnd.android.cursor.item/vnd.com.android.test.provider.table2";
default:
break;
}
return null;
}
用数据库配合上述方法
一般创建ContentProvider都要配合这个应用的数据库,配合数据库的使用一般是这样的:
- 在onCreate方法中建立数据库
- 分别在query insert update delete方法中调用SQLiteDatabase的同名方法来实现。
广告时间
我是N0tExpectErr0r,一名广东工业大学的大二学生
欢迎来到我的个人博客,所有文章均在个人博客中同步更新哦
http://blog.N0tExpectErr0r.cn