前言:
总结这篇文章之前我们先来回顾一下Android Sqlite数据库,参考文章:http://www.cnblogs.com/whoislcj/p/5506294.html,Android程序内部数据存储如果使用Sqlite数据库,那么Android 如何实现程序间数据共享?Android 提供了一种机制可以实现程序间的数据共享,它就是Android 四大组件之一ContentProvider,Android为存储和获取数据提供统一的接口,用于实现程序间数据共享,不要将其理解为数据库。
为什么说是熟悉又陌生呢?因为我们经常使用到,Android内置的许多数据都是采用ContentProvider,比如图片,视频,音频,手机联系人等,至于陌生那是因为我很少自己去实现一个ContentProvider,今天我们重点是来实现一个自定义ContentProvider。
ContentProvider类简介:
1.) 我们一般要继承ContentProvider,那么要实现那些函数呢?
- ContentProvider() 构造函数
- onCreate() 创建数据时调用的回调函数
- insert() 插入数据
- delete() 删除数据
- update() 更新数据
- query() 查询数据
- getType() 得到数据类型
2.)URI简介:
ContentProvider通过URI来访问数据执行增删改查的操作,一个完整的URI有 content://自定义ContentProvider/xxx数据库名称
我们先声明一个作用域:
//访问URI作用域 public static final String CONTENT_URI="com.whoislcj.testsqlite.personprovider";
对应URI举例说明一下:
- content://com.whoislcj.testsqlite.personprovider/person 返回person所以数据
- content://com.whoislcj.testsqlite.personprovider/person/10 返回id为10的person数据
3.)UriMatcher简介
主要用于匹配Uri,为什么要匹配Uri呢?通过上面的Uri举例可以看出操作域不一样,对于执行一个delete、update、query来说我们要获取参数参数执行不能对应操作。
使用:
//定义一个UriMatcher类对象,用来匹配Uri的。 private static final UriMatcher uriMatcher; //集合操作 public static final int INCOMING_COLLECTION = 1; //单个ID操作 public static final int INCOMING_SIGNAL = 2; static { //常量UriMatcher.NO_MATCH表示不匹配任何路径的返回码 uriMatcher = new UriMatcher(UriMatcher.NO_MATCH); //如果match()方法匹配com.whoislcj.testsqlite.personprovider/person路径,返回匹配码为1 uriMatcher.addURI(CONTENT_URI, "person", INCOMING_COLLECTION);//添加需要匹配uri,如果匹配就会返回匹配码 //如果match()方法匹配content://com.ljq.provider.personprovider/person/230路径,返回匹配码为2 uriMatcher.addURI(CONTENT_URI, "person/#", INCOMING_SIGNAL);//#号为通配符 }
4.)ContentUris简介
ContentUris是对URI的操作类,比如获取URI路径里的参数,或者给URI拼接一个参数
举例说明:
- long id = ContentUris.parseId(uri);//从uri中获取id
- Uri rowUri = ContentUris.withAppendedId(uri, rowId);//uri追加id 生成该条数据完整的URI地址
5.)ContentResolver简介
ContentResolver主要用于为外部程序提供增删改查的操作函数,也可以注册观察者来监听数据的变化。
6.)自定义ContentProvider具体实现:
public class PersonProvider extends ContentProvider { // DatabaseHelper操作句柄 private DBHelper dbHelper; //访问URI public static final String CONTENT_URI="com.whoislcj.testsqlite.personprovider"; // 数据集的MIME类型字符串则应该以vnd.android.cursor.dir/开头 public static final String CONTENT_TYPE = "vnd.android.cursor.dir/person"; // 单一数据的MIME类型字符串应该以vnd.android.cursor.item/开头 public static final String CONTENT_TYPE_ITME = "vnd.android.cursor.item/person"; //定义一个UriMatcher类对象,用来匹配Uri的。 private static final UriMatcher uriMatcher; //集合操作 public static final int INCOMING_COLLECTION = 1; //单个ID操作 public static final int INCOMING_SIGNAL = 2; static { //常量UriMatcher.NO_MATCH表示不匹配任何路径的返回码 uriMatcher = new UriMatcher(UriMatcher.NO_MATCH); //如果match()方法匹配com.whoislcj.testsqlite.personprovider/person路径,返回匹配码为1 uriMatcher.addURI(CONTENT_URI, "person", INCOMING_COLLECTION);//添加需要匹配uri,如果匹配就会返回匹配码 //如果match()方法匹配content://com.ljq.provider.personprovider/person/230路径,返回匹配码为2 uriMatcher.addURI(CONTENT_URI, "person/#", INCOMING_SIGNAL);//#号为通配符 } public PersonProvider() { } /** * 回调函数,在ContentProvider创建的时候,就会运行 * 作用获取操作用户的句柄 */ @Override public boolean onCreate() { //这里会调用 DBHelper的构造函数创建一个数据库; dbHelper = new DBHelper(getContext()); return true; } /** * 执行插入数据函数 * * @param uri * @param values * @return */ @Override public Uri insert(Uri uri, ContentValues values) { //获取一个可写的数据库 SQLiteDatabase db = dbHelper.getWritableDatabase(); //调用数据库的插入操作 也可以自己构造sql语句 执行 db.execSQL();相对比较麻烦 long rowId = db.insert(DBHelper.TABLE_NAME, "", values); //判断是否插入成功 if (rowId > 0) { Uri rowUri = ContentUris.withAppendedId(uri, rowId);//uri追加id 生成该条数据完整的URI地址 getContext().getContentResolver().notifyChange(uri, null); return rowUri; } throw new SQLException("Failed to insert row" + uri); } /** * 删除数据操作 * * @param uri * @param selection * @param selectionArgs * @return */ @Override public int delete(Uri uri, String selection, String[] selectionArgs) { //获取一个可写的数据库 SQLiteDatabase db = dbHelper.getWritableDatabase(); int count = 0; switch (uriMatcher.match(uri)) { case INCOMING_COLLECTION: //执行删除操作 count = db.delete(DBHelper.TABLE_NAME, selection, selectionArgs); getContext().getContentResolver().notifyChange(uri, null); break; case INCOMING_SIGNAL: long id = ContentUris.parseId(uri);//从uri中获取id String where = "> 删除指定id的记录 where += !TextUtils.isEmpty(selection) ? " and (" + selection + ")" : ""; // 把其它条件附加上 count = db.delete(DBHelper.TABLE_NAME, where, selectionArgs); getContext().getContentResolver().notifyChange(uri, null); break; default: throw new SQLException("Failed to delete row " + uri); } //关闭数据库 db.close(); return count; } /** * 更新数据操作 * * @param uri * @param values * @param selection * @param selectionArgs * @return */ @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { //获取一个可写的数据库 SQLiteDatabase db = dbHelper.getWritableDatabase(); int count = 0; switch (uriMatcher.match(uri)) { case INCOMING_COLLECTION: //执行更新数据 count = db.update(DBHelper.TABLE_NAME, values, selection, selectionArgs); getContext().getContentResolver().notifyChange(uri, null); break; case INCOMING_SIGNAL: long id = ContentUris.parseId(uri);//从uri中获取id String where = "> 删除指定id的记录 where += !TextUtils.isEmpty(selection) ? " and (" + selection + ")" : "";// 把其它条件附加上 //执行更新数据 count = db.update(DBHelper.TABLE_NAME, values, where, selectionArgs); getContext().getContentResolver().notifyChange(uri, null); break; default: throw new SQLException("Failed to update row " + uri); } //关闭数据库 db.close(); return count; } /** * 查询操作 * * @param uri * @param projection * @param selection * @param selectionArgs * @param sortOrder * @return */ @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { //获取一个可读的数据库 SQLiteDatabase db = dbHelper.getReadableDatabase(); Cursor cursor = null; switch (uriMatcher.match(uri)) { case INCOMING_COLLECTION: //执行查询 cursor = db.query(DBHelper.TABLE_NAME, projection, selection, selectionArgs, null, null, sortOrder); break; case INCOMING_SIGNAL: long id = ContentUris.parseId(uri);//从uri中获取id String where = "> 删除指定id的记录 where += !TextUtils.isEmpty(selection) ? " and (" + selection + ")" : "";// 把其它条件附加上 cursor = db.query(DBHelper.TABLE_NAME, projection, where, selectionArgs, null, null, sortOrder); break; default: throw new SQLException("Failed to query " + uri); } return cursor; } /** * 该方法用于返回当前Url所代表数据的MIME类型。 * * @param uri * @return */ @Override public String getType(Uri uri) { switch (uriMatcher.match(uri)) { case INCOMING_COLLECTION: return CONTENT_TYPE; case INCOMING_SIGNAL: return CONTENT_TYPE_ITME; default: throw new IllegalArgumentException("Unknown URI " + uri); } } }