内容提供器用法一般有两种,一种是使用现有的内容提供器来读取和操作相应程序中的数据,另一种是创建自己的内容提供器给我们程序的数据提供外部访问接口。
1. ContentResolver
对于一个应用程序来说,如果想要访问内容提供器中共享的数据,就一定要借助ContentResolver类,可以通过Context中的getContentResolver()方法获取到该类的实例。ContentResolver中提供了一系列的方法用于对数据进行CRUD操作,insert(), update(), delete(), query()。
ContentResolver中的增删改查不接受表名参数,而是使用一个Uri参数替代,这个参数被称为内容URI。内容URI给内容提供器中的数据建立了唯一标识符,它主要由两部分组成:authority和path。authority是用于对不同的应用程序做区分的,一般采用程序包名的方式来命名,path则是用于对同一应用程序中不同的表作区分,通常加到authority后面。还需要在字符串的头部加上协议声明,因此,内容URI最标准的格式写法如下:
content://com.example.app.provider/table1
content://com.example.app.provider/table2
在我们得到了URI字符串之后,我们还需要将他解析成Uri对象才可以作为参数传入,解析的方法也很简单:
Uri uri = Uri.parse(“content://com.example.app.provider/table1”);
现在我们就可以使用这个Uri对象来查询table1表中的数据了:
Cursor cursor = getContentResolver().query(
uri,
projection,
selection,
selectionArgs,
sortOrder);
query()方法参数 | 描述 |
uri | 指定查询某个应用程序下的某一张表 |
projection | 指定查询的列名 |
selection | 指定where的约束条件 |
selectionArgs | 为where中的占位符提供具体的值 |
orderBy | 指定查询结果的排序方式 |
if (cursor != null) {
while (cursor.moveToNext()) {
String column1 = cursor.getString(cursor.getColumnIndex(column1));
String column2 = cursor.getString(cursor.getColumnIndex(column2));
}
cursor.close();
}
添加数据:
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"});
注意上述代码使用了selection和selectionArgs参数来对想要更新的数据进行约束,以防止所有的行都会受影响。
删除数据:
getContentResolver().delete(uri, "column2 = ?", new String[] {"1"});
2. 创建自己的内容提供器
新建一个ContentProvider
public class MyContentProvider extends ContentProvider {
public MyContentProvider() {
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
// Implement this to handle requests to delete one or more rows.
throw new UnsupportedOperationException("Not yet implemented");
}
@Override
public String getType(Uri uri) {
// TODO: Implement this to handle requests for the MIME type of the data
// at the given URI.
throw new UnsupportedOperationException("Not yet implemented");
}
@Override
public Uri insert(Uri uri, ContentValues values) {
// TODO: Implement this to handle requests to insert a new row.
throw new UnsupportedOperationException("Not yet implemented");
}
@Override
public boolean onCreate() {
// TODO: Implement this to initialize your content provider on startup.
return false;
}
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
// TODO: Implement this to handle query requests from clients.
throw new UnsupportedOperationException("Not yet implemented");
}
@Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
// TODO: Implement this to handle requests to update one or more rows.
throw new UnsupportedOperationException("Not yet implemented");
}
}
继承ContentProvider ,实现6个抽象方法:
1)onCreate()
初始化内容提供器的时候调用,通常在这里完成对数据库的创建和升级等操作,返回true表示内容提供器初始化成功。注意,只有当存在ContentResolver尝试访问我们程序中的数据时,内容提供器才会被初始化。
2)query()
3)insert()
4)update()
5)delete()
6)getType()
根据传入的内容URI来返回相应的MIME类型
内容URI的格式主要由以下两种:
content://com.example.app.provider/table1
content://com.example.app.provider/table1/1
以路径结尾表示期望访问该表中的数据,以id结尾表示期望访问该表中拥有相应id的数据,我们可以使用通配符的方式来分别匹配这两种格式的URI,规则如下:
- *:表示匹配任意长度的任意字符
- #:表示匹配任意长度的数字
所以,一个能够匹配任意表的内容URI格式就可以写成:
content://com.example.app.provider/*
而一个能够匹配table1表中任意一行数据的内容URI格式就可以写成:
content://com.example.app.provider/table1/#
接着,我们再借助UriMacher这个类就可以轻松地实现匹配内容URI 的功能。UriMacher先addURI加入uri,这样在调用UriMacher的match() 方法时,就可以判断出调用方期望访问的是哪张表中的数据了。修改MyContentProvider中的代码:
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;
private static UriMatcher uriMatcher;
static {
uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
uriMatcher.addURI("com.example.xiaoxiong.test.mycontetnprovider","table1",TABLE1_DIR);
uriMatcher.addURI("com.example.xiaoxiong.test.mycontetnprovider","table1/#", TABLE1_ITEM);
uriMatcher.addURI("com.example.xiaoxiong.test.mycontetnprovider","table2", TABLE2_DIR);
uriMatcher.addURI("com.example.xiaoxiong.test.mycontetnprovider","table2/#", TABLE2_ITEM);
}
@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;
default:
}
}