ContentProvider
Posted 指尖上的代码
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ContentProvider相关的知识,希望对你有一定的参考价值。
1.Content Resolver
每个应用程序都有一个ContentResolver实例,可以使用getContentResolver方法来对其进行访问。当Content Provider公开数据时,ContentResolver是用来在这些Content Provider上进行查询和执行事物的对应类。ContentResolver不需要知道与它交互的Content Provider的具体实现,每个查询和事物只需要简单的接受一个指定交互的Content Provider的URI就行。
ContentResolver cr = getContentResolver();
(1).Content Provider的URI构成。
标准的URI主要分为两个部分。权限(authority)和路径(path),权限是用来区分不同的应用程序的,一般为避免冲突,都是以程序包名命名+provider命名权限,如com.example.app.provider,路径则是对不同的数据表进行区分比如table_1,table_2。内容URI字符串最标准的书写形式。
content://com.example.app.provider/table_1
得到内容URI之后,还要将它解析为Uri对象才可以作为参数传入,解析很简单,如下:
Uri uri = Uri.parse("content://com.example.app.provider/table_1");
(2)查询数据
查询与Sqlite语句类似,如下:
Cursor cursor = getContentResolver().query(uri, projection, selection, selectionArgs, sortOrder);
查询完成后返回一个Cursor对象,通过遍历,就可以将数据逐一的取出来了
if (cursor != null) { while (cursor.moveToNext()) { String column1 = cursor.getString(cursor.getColumnIndex("column1")); int column2 = cursor.getInt(cursor.getColumnIndex("column2")); } cursor.close(); }
记得Cursor一定要关闭
(3)增、删、改
最难的查询都会了,增、删、改就更简单了,示例如下:
1 ContentValues values = new ContentValues(); 2 values.put("column1", "text"); 3 values.put("column2", 1); 4 //增加数据 5 getContentResolver().insert(uri, values); 6 //更新数据 7 getContentResolver().update(uri, values, "column1 = ? and column2 = ?", new String[] {"text", "1"}); 8 //删除数据 9 getContentResolver().delete(uri, "column2 = ?", new String[] { "1" });
2.ContentProvider
(1)创建一个内容提供器,只需要继承ContentProvider,重写其中的onCreate,query,insert,update,delete,getType方法。
1 public class MyContentProvider extends ContentProvider { 2 @Override 3 public boolean onCreate() { 4 return false; 5 } 6 7 @Nullable 8 @Override 9 public Cursor query(Uri uri, String[] strings, String s, String[] strings1, String s1) { 10 return null; 11 } 12 13 @Nullable 14 @Override 15 public String getType(Uri uri) { 16 return null; 17 } 18 19 @Nullable 20 @Override 21 public Uri insert(Uri uri, ContentValues contentValues) { 22 return null; 23 } 24 25 @Override 26 public int delete(Uri uri, String s, String[] strings) { 27 return 0; 28 } 29 30 @Override 31 public int update(Uri uri, ContentValues contentValues, String s, String[] strings) { 32 return 0; 33 } 34 }
(2)注册ContentProvider
在ContentResolver找到ContentProvider之前,必须要在androidManifest.xml清单中注册ContentProvider,注册是在provider中实现的,该节点包含name和authorities属性。其中authorities用来设定ContentProvider的基本URI。完成注册的ContentProvider示例如下。
<provider android:authorities="com.example.firstcode.provider" android:name="MyContentProvider"/>
(3)实现ContentProvider支持查询
若想实现ContentProvider支持查询,就必需实现query和getType方法。query方法如下:
1 @Override 2 public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { 3 switch (uriMatcher.match(uri)) { 4 case TABLE1_DIR: 5 // 查询table1表中的所有数据 6 break; 7 case TABLE1_ITEM: 8 // 查询table1表中的单条数据 9 break; 10 case TABLE2_DIR: 11 // 查询table2表中的所有数据 12 break; 13 case TABLE2_ITEM: 14 // 查询table2表中的单条数据 15 break; 16 default: 17 break; 18 } 19 }
getType方法是每个内容提供器必须提供的方法,用于获取Uri对象对应的MIME类型。一个MIME字符串主要包括三个部分:
• 必须以vnd开头
• 若Uri以路径结尾,则后接android.cursor.dir/,若以id结尾,则后接android.cursor.item/
• 最后接上vnd.<authroities>.<path>
所以对于content://com.example.app.provider/table1这个Uri字符串,对应的MIME类型为:
vnd.android.cursor.dir/vnd.com.example.app.provider.table1
1 @Nullable 2 @Override 3 public String getType(Uri uri) { 4 switch (mUriMatcher.match(uri)){ 5 case BOOK_DIR: 6 return "vnd.android.cursor.dir/vnd.com.example.firstcode.provider.book"; 7 case BOOK_ITEM: 8 return "vnd.android.cursor.item/vnd.com.example.firstcode.provider.book"; 9 case CATEGORY_DIR: 10 return "vnd.android.cursor.dir/vnd.com.example.firstcode.provider.category"; 11 case CATEGORY_ITEM: 12 return "vnd.android.cursor.item/vnd.com.example.firstcode.provider.category"; 13 } 14 return null; 15 }
一个完整的ContentProvider代码示例如下:
1 public class MyContentProvider extends ContentProvider { 2 3 4 public static final int BOOK_DIR = 0; 5 6 public static final int BOOK_ITEM = 1; 7 8 public static final int CATEGORY_DIR = 2; 9 10 public static final int CATEGORY_ITEM = 3; 11 12 public static final String AUTHORITY = "com.example.firstcode.provider"; 13 14 private static UriMatcher mUriMatcher = null; 15 16 private MyDatabaseHelper mDatabaseHelper = null; 17 18 /** 19 * #表示匹配任意数字,*表示匹配任意长度字符 20 * 21 */ 22 static { 23 mUriMatcher = new UriMatcher(UriMatcher.NO_MATCH); 24 mUriMatcher.addURI(AUTHORITY,"book",BOOK_DIR); 25 mUriMatcher.addURI(AUTHORITY,"book/#",BOOK_ITEM); 26 mUriMatcher.addURI(AUTHORITY,"category",CATEGORY_DIR); 27 mUriMatcher.addURI(AUTHORITY,"category/#",CATEGORY_ITEM); 28 } 29 @Override 30 public boolean onCreate() { 31 mDatabaseHelper = new MyDatabaseHelper(getContext(),"book_store.db",null,2); 32 return true; 33 } 34 35 @Nullable 36 @Override 37 public Cursor query(Uri uri, String[] projection, String selection, 38 String[] selectionArgs, String sortOrder) { 39 40 SQLiteDatabase database = mDatabaseHelper.getReadableDatabase(); 41 Cursor cursor = null; 42 switch (mUriMatcher.match(uri)){ 43 case BOOK_DIR: 44 cursor = database.query("book",projection,selection,selectionArgs,null,null,sortOrder); 45 break; 46 case BOOK_ITEM: 47 String bookId = uri.getPathSegments().get(1); 48 cursor = database.query("book",projection,"id = ?",new String[]{bookId},null,null,sortOrder); 49 break; 50 case CATEGORY_DIR: 51 cursor = database.query("category",projection,selection,selectionArgs,null,null,sortOrder); 52 break; 53 case CATEGORY_ITEM: 54 String categoryId = uri.getPathSegments().get(1); 55 cursor = database.query("category",projection,"id = ?",new String[]{categoryId},null,null,sortOrder); 56 break; 57 } 58 return cursor; 59 } 60 61 @Nullable 62 @Override 63 public String getType(Uri uri) { 64 switch (mUriMatcher.match(uri)){ 65 case BOOK_DIR: 66 return "vnd.android.cursor.dir/vnd.com.example.firstcode.provider.book"; 67 case BOOK_ITEM: 68 return "vnd.android.cursor.item/vnd.com.example.firstcode.provider.book"; 69 case CATEGORY_DIR: 70 return "vnd.android.cursor.dir/vnd.com.example.firstcode.provider.category"; 71 case CATEGORY_ITEM: 72 return "vnd.android.cursor.item/vnd.com.example.firstcode.provider.category"; 73 } 74 return null; 75 } 76 77 @Nullable 78 @Override 79 public Uri insert(Uri uri, ContentValues contentValues) { 80 SQLiteDatabase database = mDatabaseHelper.getReadableDatabase(); 81 Uri uriReturn = null; 82 switch (mUriMatcher.match(uri)){ 83 case BOOK_DIR: 84 case BOOK_ITEM: 85 long bookId = database.insert("book",null,contentValues); 86 uriReturn = Uri.parse("content://"+AUTHORITY+"/book/"+bookId); 87 break; 88 case CATEGORY_DIR: 89 case CATEGORY_ITEM: 90 long categoryId = database.insert("book",null,contentValues); 91 uriReturn = Uri.parse("content://"+AUTHORITY+"/book/"+categoryId); 92 break; 93 } 94 95 return uriReturn; 96 } 97 98 @Override 99 public int delete(Uri uri, String s, String[] strings) { 100 SQLiteDatabase database = mDatabaseHelper.getReadableDatabase(); 101 int deleteRows = 0; 102 switch (mUriMatcher.match(uri)){ 103 case BOOK_DIR: 104 deleteRows = database.delete("book",s,strings); 105 break; 106 case BOOK_ITEM: 107 String bookId = uri.getPathSegments().get(1); 108 deleteRows = database.delete("book","id = ?",new String[]{bookId}); 109 break; 110 case CATEGORY_DIR: 111 deleteRows = database.delete("category",s,strings); 112 break; 113 case CATEGORY_ITEM: 114 String category = uri.getPathSegments().get(1); 115 deleteRows = database.delete("category","id = ?",new String[]{category}); 116 break; 117 } 118 return deleteRows; 119 } 120 121 @Override 122 public int update(Uri uri, ContentValues contentValues, String s, String[] strings) { 123 SQLiteDatabase database = mDatabaseHelper.getReadableDatabase(); 124 int updateRows = 0; 125 switch (mUriMatcher.match(uri)){ 126 case BOOK_DIR: 127 updateRows = database.update("book",contentValues,s,strings); 128 break; 129 case BOOK_ITEM: 130 String bookId = uri.getPathSegments().get(1); 131 updateRows = database.update("book",contentValues,"id = ?",new String[]{bookId}); 132 break; 133 case CATEGORY_DIR: 134 updateRows = database.update("category",contentValues,s,strings); 135 break; 136 case CATEGORY_ITEM: 137 String categoryId = uri.getPathSegments().get(1); 138 updateRows = database.update("category",contentValues,"id = ?",new String[]{categoryId}); 139 140 break; 141 } 142 return updateRows; 143 } 144 }
以上是关于ContentProvider的主要内容,如果未能解决你的问题,请参考以下文章
为啥 ContentProvider 在 App 更新后返回空游标?
Android - 将 Dao 模式与 contentProvider 一起使用