ContentProvider的使用
概述
1.ContentProvider为存储和读取数据提供了统一的接口
2.使用ContentProvider,应用程序可以实现数据共享
3.android内置的许多数据都是使用ContentProvider形式,供开发者调用的(如视频,音频,图片,通讯录等)
了解URI
UriMatcher
UriMatcher用于匹配Uri路径
- 创建URiMatcher
UriMatcher sMatcher = new UriMatcher(UriMatcher.NO_MATCH);
- 设置路径及匹配码
addURI(String authority, String path, int code)
- 自定义ContentProvider类的AUTHORITY字符串
- path表示需要匹配的路径
- code表示匹配码(必须大于零),匹配则返回的值
用#代表匹配任意数字,用*来匹配任意文本
例子
sMatcher.addURI("contacts", "person",1);
- 进行匹配返回匹配码
match(Uri uri)
例子
int code = sMatcher.match(Uri.parse("content://contacts/person/10"));
ContentUris
ContentUris类用于获取Uri路径后面的ID部分
- withAppendedId(Uri contentUri, long id)用于为路径加上ID部分:
Uri uri = Uri.parse("content://contacts/person")
Uri resultUri = ContentUris.withAppendedId(uri, 10);
- parseId(Uri contentUri)方法用于从路径中获取ID部分:
Uri uri = Uri.parse("content://contacts/person/10")
long personid = ContentUris.parseId(uri);//获取的结果为:10
使用ContentProvider共享数据
继承于ContentProvider实现以下方法
- public void onCreate() 该方法在ContentProvider创建后调用,当第一次访问ContentProvider时,该ContentProvider会被创建出来,并立即回调该onCreate()方法
- public Cursor query(Uri uri, String[] projection, String selection,String[] selectionArgs, String sortOrder) 该方法用于返回当前Uri所代表的数据。
- projection 要查询出来的列名,相当于select语句select关键字后面的部分
- selection 查询条件子句,相当于select语句where关键字后面的部分,在条件子句中允许使用占位符“?”
- selectionArgs 用于为selection子句中的占位符传值
- sortOrder 表示排序方式,相当于select语句order by关键字后面的部分
- public String getType(Uri uri) 该方法用于返回当前Uri所代表数据的MIME类型。
- 如果要操作的数据属于非集合类型数据,那么MIME类型字符串应该以vnd.android.cursor.item/开头
- 如果操作的数据属于集合类型,那么MIME类型字符串应该以vnd.android.cursor.dir/开头
- public Uri insert(Uri uri, ContentValues values) 根据当前Uri插入values对应的数据
- values代表要插入的数据
- public int delete(Uri uri, String selection, String[] selectionArgs) 根据当前Uri删除对应的数据
- selection 查询条件子句,相当于where关键字后面的部分,在条件子句中允许使用占位符“?”
- selectionArgs 用于为selection子句中的占位符传值
- public int update(Uri uri, ContentValues values, String selection,String[] selectionArgs) 根据当前Uri修改对应的数据
- values 要修改的值,对应与set关键字后面的字段
- selection 查询条件子句,相当于where关键字后面的部分,在条件子句中允许使用占位符“?”
- selectionArgs 用于为selection子句中的占位符传值
当使用查询语句要返回Cursor对象时,可以使用MatrixCursor或继承MatrixCursor实现自己的Cursor来创建返回的Cursor对象
使用ContentResolver操作ContentProvider中的数据
使用getContentResolver();
获得ContentResolver对象
- 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中获取数据。
监听ContentProvider中数据的变化
设置监听器
getContentResolver().registerContentObserver(uri,true,new ContentObserver(new Handler()) { @Override public void onChange(boolean selfChange) { super.onChange(selfChange); } });
其中第二个参数为true时,只要uri是其子层也会被通知,如果为false,则只有uri完全匹配才行。
- 通知数据发生变化
在自己ContentProvider类的方法中调用。getContext().getContentResolver().notifyChange(uri,null);
权限设置
ContentProvider通过在AndroidManifest中设置读权限(android:readPermission)写权限(android:writePermission)读写权限(android:permission)(但优先级没前面两个高)来控制权限,通过path-permission子标签能进行更详细的控制,grant-uri-permission子标签用于当一个有权限访问的组件调用一个无权限访问的组件访问时ContentProvider可以访问
具体属性请看provider属性详解
AsyncQueryHandler
// 定义一个handler,采用的是匿名类的方式,只处理query,因此只重写了onQueryComplete函数:
queryHandler = new AsyncQueryHandler(this.getContentResolver()){
// 传入的是一个ContentResolver实例,所以必须在OnCreate后实例化该Handler类
@Override
protected void onQueryComplete(int token, Object cookie, Cursor cursor) {
// 在这里你可以获得一个cursor和你传入的附加的token和cookie。
// 该方法在当前线程下(如果传入的是默认的Looper话),可以自由设定UI信息
}
};
调用时只需要调用
startQuery(int token, Object cookie, ContentURI uri,
String[] projection, String selection, String[] selectionArgs, String sortOrder)
函数即可:
例如:
queryHandler.startQuery(token, cookie, uri, projection, selection, selectionArgs, sortBy);
参考资料
Android ContentProvider和Uri详解 (绝对全面)
一些ContentProvider和 AsyncQueryHandler 联合使用技巧