Android 四大组件之ContentProvider
本文由 Luzhuo 编写,转发请保留该信息.
原文: http://blog.csdn.net/Rozol/article/details/79606186
内容提供者 (提供数据给第三方应用访问)
四大组件(Activity / BroadcastReceiver / Service / ContentProvider)之一
四大组件均运行于主线程
使用
清单文件配置
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="me.luzhuo.contentproviderdemo"> <!-- 添加访问权限 --> <uses-permission android:name="luzhuo.me.read" /> <uses-permission android:name="luzhuo.me.write" /> <!-- 声明权限,只有声明才能识别 --> <permission android:name="aa.bb.cc.read"/> <permission android:name="aa.bb.cc.write"/> <application ...> <...> <!-- 内容提供者 --> <!-- authorities:主机名; readPermission:读权限; writePermission:写权限 --> <provider android:name=".PersonContentProvider" android:authorities="luzhuo.me.provider" android:readPermission="luzhuo.me.read" android:writePermission="luzhuo.me.write" > </provider> </application> </manifest>
编写 SQLiteOpenHelper 数据库帮助类 (略)
编写 ContentProvider 内容提供者
public class PersonContentProvider extends ContentProvider { public static final String AUTHORITY = "luzhuo.me.provider"; // 主机名 private static final int PRESON_INSERT_CODE = 0; //操作person表添加操作的uri匹配码 private static final int PRESON_DELETE_CODE = 1; private static final int PRESON_UPDATE_CODE = 2; private static final int PRESON_QUERY_ALL_CODE = 3; private static final int PRESON_QUERY_ITEM_CODE = 4; private static UriMatcher uriMatcher; private PersonSQLiteOpenHelper mOpenHelper; //person数据库帮助对象 /* URI content://luzhuo.me.provider/person/10 \------/ \-----------------/ \---/ \--/ scheme authority path ID scheme:声明一个ContentProvider控制这些数据 主机名/授权(Authoryty):定义那个ContentProvider提供这些数据 path路径:URI下的某个Item ID:定义Uri时使用#号占位符代替,使用时替换成对应的数字 content://luzhuo.me.provider/person/# #表示数据id (#代表任意数字) content://luzhuo.me.provider/person/* *来匹配任意文本 */ static{ uriMatcher = new UriMatcher(UriMatcher.NO_MATCH); //不匹配返回的类型 //添加一些rui(分机号) // content://luzhuo.me.provider/person/insert uriMatcher.addURI(AUTHORITY, //authority 主机名 "person/insert", //path 分机号 PRESON_INSERT_CODE); //code 匹配码 //0 // content://luzhuo.me.provider/person/delete uriMatcher.addURI(AUTHORITY, "person/delete", PRESON_DELETE_CODE); //1 // content://luzhuo.me.provider/person/update uriMatcher.addURI(AUTHORITY, "person/update", PRESON_UPDATE_CODE); //2 // content://luzhuo.me.provider/person/queryAll uriMatcher.addURI(AUTHORITY, "person/queryAll", PRESON_QUERY_ALL_CODE); //3 // content://luzhuo.me.provider/person/query/# uriMatcher.addURI(AUTHORITY, "person/query/#", PRESON_QUERY_ITEM_CODE); //4 } @Override public boolean onCreate() { mOpenHelper = new PersonSQLiteOpenHelper(getContext()); return true; } @Nullable @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { SQLiteDatabase db = mOpenHelper.getReadableDatabase(); switch (uriMatcher.match(uri)) { case PRESON_QUERY_ALL_CODE: //查询所有人的uri if(db.isOpen()){ Cursor cursor = db.query("person", projection, selection, selectionArgs, null, null,sortOrder); return cursor; //db.close(); 返回cursor结果集时,不可以关闭数据库 } case PRESON_QUERY_ITEM_CODE: //查询的是单条数据,uri末尾处有一个id if(db.isOpen()){ long id = ContentUris.parseId(uri); Cursor cursor = db.query("person", projection, "_id = ?", new String[]{id+""},null,null,sortOrder); return cursor; } break; default: throw new IllegalArgumentException("uri不匹配:"+uri); } return null; } @Nullable @Override public String getType(Uri uri) { switch (uriMatcher.match(uri)) { case PRESON_QUERY_ALL_CODE: //返回多条的MIME-type return "vnd.android.cursor.dir/person"; case PRESON_QUERY_ITEM_CODE: //返回单条的MIME-TYPE return "vnd.android.cursor.item/person"; default: break; } return null; } @Nullable @Override public Uri insert(Uri uri, ContentValues values) { switch (uriMatcher.match(uri)) { case PRESON_INSERT_CODE: //添加人到person表中 SQLiteDatabase db = mOpenHelper.getWritableDatabase(); if(db.isOpen()){ long id = db.insert("person", null, values); //通知内容观察者改变 getContext().getContentResolver().notifyChange(Uri.parse("content://".concat(AUTHORITY)), null); db.close(); return ContentUris.withAppendedId(uri, id); //追加id } break; default: throw new IllegalArgumentException("uri不匹配:"+uri); } return null; } @Override public int delete(Uri uri, String selection, String[] selectionArgs) { switch (uriMatcher.match(uri)) { case PRESON_DELETE_CODE: //在person表中删除数据的 SQLiteDatabase db = mOpenHelper.getWritableDatabase(); if(db.isOpen()){ int count = db.delete("person", selection, selectionArgs); //通知内容观察者改变 getContext().getContentResolver().notifyChange(Uri.parse("content://".concat(AUTHORITY)), null); db.close(); return count; } break; default: throw new IllegalArgumentException("uri不匹配:"+uri); } return 0; } @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { switch (uriMatcher.match(uri)) { case PRESON_UPDATE_CODE: //更新person表的操作 SQLiteDatabase db = mOpenHelper.getWritableDatabase(); if(db.isOpen()){ int count = db.update("person", values, selection, selectionArgs); //通知内容观察者改变 getContext().getContentResolver().notifyChange(Uri.parse("content://".concat(AUTHORITY)), null); db.close(); return count; } break; default: throw new IllegalArgumentException("uri不匹配:"+uri); } return 0; } }
使用(分为同步和异步)
public class TestCase extends AndroidTestCase { private static final String TAG = TestCase.class.getSimpleName(); /** * 同步插入数据 */ public void testInsert(){ Uri uri = Uri.parse("content://".concat(PersonContentProvider.AUTHORITY).concat("/person/insert")); ContentResolver resolver = getContext().getContentResolver(); //内容提供者对象 ContentValues values = new ContentValues(); values.put("name", "lwangwu"); values.put("age", 63); uri = resolver.insert(uri, values); //执行 long id = ContentUris.parseId(uri); //分析出id Log.i(TAG, "添加到:"+id); } /** * 异步插入数据 */ public void testAsyncInsert(){ Uri uri = Uri.parse("content://".concat(PersonContentProvider.AUTHORITY).concat("/person/insert")); ContentValues values = new ContentValues(); values.put("name", "lwangwu"); values.put("age", 63); AsyncQueryHandler asyncQuery = new AsyncQueryHandler(getContext().getContentResolver()) { @Override protected void onInsertComplete(int token, Object cookie, Uri uri) { super.onInsertComplete(token, cookie, uri); long id = ContentUris.parseId(uri); //分析出id Log.i(TAG, "添加到:"+id); } }; asyncQuery.startInsert(0, null, uri, values); } /** * 同步删除数据 */ public void testDelete(){ Uri uri = Uri.parse("content://".concat(PersonContentProvider.AUTHORITY).concat("/person/delete")); ContentResolver resolver = getContext().getContentResolver(); String where = "_id = ?"; String[] selectionArgs = {"3"}; int count = resolver.delete(uri, where, selectionArgs); Log.i(TAG, "删除行:"+count); } /** * 异步删除数据 */ public void testAsyncDelete(){ Uri uri = Uri.parse("content://".concat(PersonContentProvider.AUTHORITY).concat("/person/delete")); String where = "_id = ?"; String[] selectionArgs = {"3"}; AsyncQueryHandler asyncQuery = new AsyncQueryHandler(getContext().getContentResolver()) { @Override protected void onDeleteComplete(int token, Object cookie, int result) { super.onDeleteComplete(token, cookie, result); Log.i(TAG, "result:" + result); } }; asyncQuery.startDelete(0, null, uri, where, selectionArgs); } /** * 同步更新数据 */ public void testUpdate(){ Uri uri = Uri.parse("content://".concat(PersonContentProvider.AUTHORITY).concat("/person/update")); ContentResolver resolver = getContext().getContentResolver(); ContentValues values = new ContentValues(); values.put("name", "lisi"); int count = resolver.update(uri, values, "_id = ?", new String[]{"5"}); Log.i(TAG, "更新行"+count); } /** * 异步更新数据 */ public void testAsyncUpdate(){ Uri uri = Uri.parse("content://".concat(PersonContentProvider.AUTHORITY).concat("/person/update")); ContentValues values = new ContentValues(); values.put("name", "lisi"); AsyncQueryHandler asyncQuery = new AsyncQueryHandler(getContext().getContentResolver()) { @Override protected void onUpdateComplete(int token, Object cookie, int result) { super.onUpdateComplete(token, cookie, result); Log.i(TAG, "result:" + result); } }; asyncQuery.startUpdate(0, null, uri, values, "_id = ?", new String[]{"5"}); } /** * 同步查询所有数据 */ public void testQueryAll(){ Uri uri = Uri.parse("content://".concat(PersonContentProvider.AUTHORITY).concat("/person/queryAll")); ContentResolver resolver = getContext().getContentResolver(); Cursor cursor = resolver.query(uri, new String[]{"_id","name","age"}, null, null, "_id desc"); if(cursor != null && cursor.getCount()>0){ int id; String name; int age; while(cursor.moveToNext()){ id = cursor.getInt(0); name = cursor.getString(1); age = cursor.getInt(2); Log.i(TAG, "id:"+id+",name:"+name+",age:"+age); } cursor.close(); } } /** * 异步查询所有数据 */ public void testAsycQueryAll(){ Uri uri = Uri.parse("content://".concat(PersonContentProvider.AUTHORITY).concat("/person/queryAll")); AsyncQueryHandler asyncQuery = new AsyncQueryHandler(getContext().getContentResolver()) { @Override protected void onQueryComplete(int token, Object cookie, Cursor cursor) { super.onQueryComplete(token, cookie, cursor); if(cursor != null && cursor.getCount()>0){ int id; String name; int age; while(cursor.moveToNext()){ id = cursor.getInt(0); name = cursor.getString(1); age = cursor.getInt(2); Log.i(TAG, "id:"+id+",name:"+name+",age:"+age); } cursor.close(); } } }; asyncQuery.startQuery(0, null, uri, new String[]{"_id","name","age"}, null, null, "_id desc"); } /** * 同步查询指定一条数据 */ public void testQuerySingleItem(){ Uri uri = Uri.parse("content://".concat(PersonContentProvider.AUTHORITY).concat("/person/query/#")); //在uri的末尾添加一个id "content://".concat(PersonContentProvider.AUTHORITY).concat("/person/query/20") uri = ContentUris.withAppendedId(uri, 5); //内容提供者访问对象 ContentResolver resolver = getContext().getContentResolver(); Cursor cursor = resolver.query(uri, new String[]{"_id","name","age"}, null, null, null); if(cursor != null && cursor.moveToFirst()){ int id = cursor.getInt(0); String name = cursor.getString(1); int age = cursor.getInt(2); cursor.close(); Log.i(TAG, "id:"+id+",name:"+name+",age:"+age); } } /** * 异步查询指定一条数据 */ public void testAsyncQuerySingleItem(){ Uri uri = Uri.parse("content://".concat(PersonContentProvider.AUTHORITY).concat("/person/query/#")); uri = ContentUris.withAppendedId(uri, 5); // AsyncQueryHandler 异步查询类 AsyncQueryHandler asyncQuery = new AsyncQueryHandler(getContext().getContentResolver()) { @Override protected void onQueryComplete(int token, Object cookie, Cursor cursor) { super.onQueryComplete(token, cookie, cursor); // 查询完成 if(cursor != null && cursor.moveToFirst()){ int id = cursor.getInt(0); String name = cursor.getString(1); int age = cursor.getInt(2); cursor.close(); Log.i(TAG, "id:"+id+",name:"+name+",age:"+age); } } }; // 开始异步查询数据 startQuery(token:任意数字;Object:任意对象;uri:Uri;projection:列;selection:选择语句,selectionArgs:选择条件,orderBy:排序) asyncQuery.startQuery(0, null, uri, new String[]{"_id","name","age"}, null, null, null); } }
使用内容观察者
注册内容观察者
// 注册观察者观察数据库改变 Uri uri = Uri.parse("content://".concat(PersonContentProvider.AUTHORITY)); getContentResolver().registerContentObserver(uri, true, new ContentObserver(new Handler()) { @Override public void onChange(boolean selfChange) { Log.i(TAG, "内容改变了"); } });
内容观察者通知数据改变
public Uri insert(Uri uri, ContentValues values) { switch (uriMatcher.match(uri)) { case PRESON_INSERT_CODE: SQLiteDatabase db = mOpenHelper.getWritableDatabase(); if(db.isOpen()){ long id = db.insert("person", null, values); //通知内容观察者改变 getContext().getContentResolver().notifyChange(Uri.parse("content://".concat(AUTHORITY)), null); db.close(); return ContentUris.withAppendedId(uri, id); } break; default: throw new IllegalArgumentException("uri不匹配:"+uri); } return null; }