自定义内容提供器
一.基本知识点
可以通过新建一个类去继承ContentProvider 的方式来创建一个自己的内容提供器。ContentProvider 类中有六个抽象方法,我们在使用子类继承它的时候,需要将这六个方法全部重写。新建MyProvider 继承自ContentProvider,代码如下所示:
public class MyProvider extends ContentProvider { @Override public boolean onCreate() { return false; } @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { return null; } @Override public Uri insert(Uri uri, ContentValues values) { return null; } @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { return 0; } @Override public int delete(Uri uri, String selection, String[] selectionArgs) { return 0; } @Override public String getType(Uri uri) { return null; } }
这六个方法解释如下:
1. onCreate()
初始化内容提供器的时候调用。通常会在这里完成对数据库的创建和升级等操作,返回true 表示内容提供器初始化成功,返回false 则表示失败。注意,只有当存在ContentResolver 尝试访问我们程序中的数据时,内容提供器才会被初始化。
2. query()
从内容提供器中查询数据。使用uri 参数来确定查询哪张表,projection 参数用于确定查询哪些列,selection 和selectionArgs 参数用于约束查询哪些行,sortOrder参数用于对结果进行排序,查询的结果存放在Cursor 对象中返回。
3. insert()
向内容提供器中添加一条数据。使用uri 参数来确定要添加到的表,待添加的数据保存在values 参数中。添加完成后,返回一个用于表示这条新记录的URI。
4. update()
更新内容提供器中已有的数据。使用uri 参数来确定更新哪一张表中的数据,新数据保存在values 参数中,selection 和selectionArgs 参数用于约束更新哪些行,受影响的行数将作为返回值返回。
5. delete()
从内容提供器中删除数据。使用uri 参数来确定删除哪一张表中的数据,selection和selectionArgs 参数用于约束删除哪些行,被删除的行数将作为返回值返回。
6. getType()
根据传入的内容URI 来返回相应的MIME 类型。
二.内容URI写法和访问:
一个标准的内容URI 写法是这样的:
content://com.example.app.provider/table1
这就表示调用方期望访问的是com.example.app 这个应用的table1 表中的数据。除此之外,我们还可以在这个内容URI 的后面加上一个id,如下所示:
content://com.example.app.provider/table1/1
这就表示调用方期望访问的是com.example.app 这个应用的table1 表中id 为1 的数据。
内容URI 的格式主要就只有以上两种,以路径结尾就表示期望访问该表中所有的数据,
以id 结尾就表示期望访问该表中拥有相应id 的数据。我们可以使用通配符的方式来分别匹配这两种格式的内容URI,规则如下。
1. *:表示匹配任意长度的任意字符
2. #:表示匹配任意长度的数字
所以,一个能够匹配任意表的内容URI 格式就可以写成:
content://com.example.app.provider/*
而一个能够匹配table1 表中任意一行数据的内容URI 格式就可以写成:
content://com.example.app.provider/table1/#
三.getType()方法
它是所有的内容提供器都必须提供的一个方法,用于获取Uri 对象所对应的MIME 类型。一个内容URI 所对应的MIME
字符串主要由三部分组分,Android 对这三个部分做了如下格式规定。
1. 必须以vnd 开头。
2. 如果内容URI 以路径结尾,则后接android.cursor.dir/,如果内容URI 以id 结尾,则后接android.cursor.item/。
3. 最后接上vnd.<authority>.<path>。
所以,对于content://com.example.app.provider/table1 这个内容URI,它所对应的MIME 类型就可以写成:
vnd.android.cursor.dir/vnd.com.example.app.provider.table1
对于content://com.example.app.provider/table1/1 这个内容URI,它所对应的MIME 类型就可以写成:
vnd.android.cursor.item/vnd. com.example.app.provider.table1
四.自定义的内容提供器类(仅实现了查询和增加)
public class MyContentProvider extends ContentProvider { private MyDataHelper dbHelper; public static final String AUTHORITY="com.example.guo.contentproviderdemo2.provider"; public static UriMatcher uriMatcher; static { uriMatcher = new UriMatcher(UriMatcher.NO_MATCH); uriMatcher.addURI(AUTHORITY, "book", 0); uriMatcher.addURI(AUTHORITY, "book/#", 1); } @Nullable @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { SQLiteDatabase db = dbHelper.getWritableDatabase(); Cursor cursor = null; switch (uriMatcher.match(uri)){ case 0: cursor = db.query("book", projection, selection,selectionArgs,null,null,sortOrder); break; default: break; } return cursor; } @Override public int delete(Uri uri, String selection, String[] selectionArgs) { return 0; } @Override public boolean onCreate() { dbHelper = new MyDataHelper(getContext(),"book.db", null, 3); return true; } @Nullable @Override public Uri insert(Uri uri, ContentValues values) { SQLiteDatabase db = dbHelper.getWritableDatabase(); Uri uriReturn = null; switch (uriMatcher.match(uri)){ case 0: case 1: long bookId = db.insert("book", null, values); uriReturn = Uri.parse("content://" + AUTHORITY + "/book/" + bookId); break; default: break; } return uriReturn; } @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { return 0; } @Nullable @Override public String getType(Uri uri) { switch (uriMatcher.match(uri)){ case 0: return "vnd.android.cursor.dir/vnd.com.example." + "guo.contentproviderdemo2.provider.book"; case 1: return "vnd.android.cursor.item/vnd.com.example.guo." + "contentproviderdemo2.provider.book"; } return null; } }
五.AndroidManifest.xml
<provider android:authorities="com.example.guo.contentproviderdemo2.provider" android:name="com.example.guo.contentproviderdemo2.MyContentProvider"/>
六.Activity中:
1.增加数据:
Uri uri = Uri.parse("content://com.example.guo.contentproviderdemo2.provider/book"); ContentValues values = new ContentValues(); values.put("name", "A Clash of Kings"); values.put("author", "George Martin"); values.put("pages", 1040); values.put("price", 22.85); Uri newUri = getContentResolver().insert(uri, values); String newId = newUri.getPathSegments().get(1); Toast.makeText(MainActivity.this, newId, Toast.LENGTH_LONG).show();
2.查询数据
Uri uri = Uri.parse("content://com.example.guo.contentproviderdemo2.provider/book"); Cursor cursor = getContentResolver().query(uri, null, null, null,null); if( cursor!= null ){ while (cursor.moveToNext()){ long id = cursor.getLong(cursor.getColumnIndex("id")); String name = cursor.getString(cursor.getColumnIndex("name")); Log.e("数据", id + "|" + name); } cursor.close(); }