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自学之路--ContentProvider

Android - 将 Dao 模式与 contentProvider 一起使用

联系人 contentProvider 正在返回一个空游标

解决Android的ContentProvider的cursor.moveToNext()执行后闪退的问题

Android - 查询 SMS ContentProvider?