1.1. 什么是内容提供者
内容提供者是Android中的四大组件之一,可以将应用中的数据对外进行共享
内容提供者将数据的访问方式统一,不必针对不同数据类型采取不同的访问策略
内容提供者将数据封装,只暴露出我们希望提供给其他程序的数据
内容提供者中数据更改可被监听
1.2. 创建内容提供者
定义类继承ContentProvider,根据需要重写内部方法
在清单文件的<application>节点下进行配置,<provider>标签中需要指定name和authorities属性
name为类名,包名从程序Package开始,以“.”开始
authorities:是访问Provider时的路径,要唯一
URI代表要操作的数据,由scheme、authorites、path三部分组成
content://cn.itcast.provider.itcast/person
scheme:固定为content,代表访问内容提供者
authorites:<provider>节点中的authorites属性
path:程序定义的路径,可根据业务逻辑定义
1.3. 完成CRUD方法
Ÿ 当程序调用CRUD方法时会传入Uri
Ÿ 我们通过Uri判断调用者要操作的数据
可以使用工具类UriMatcher来判断Uri
addURI方法可以添加Uri
match方法可以匹配一个Uri判断其类型
Ÿ 根据业务逻辑操作数据
1.4. 完成getType方法
Ÿ 如果返回数据是单条数据:vnd.android.cursor.item
Ÿ 如果返回数据是多条数据:vnd.android.cursor.dir
public class PersonProvider extends android.content.ContentProvider { private static final int PERSON = 0; private static final int PERSON_ID = 1; private UriMatcher matcher; private DBOpenHelper helper; @Override public boolean onCreate() { matcher = new UriMatcher(UriMatcher.NO_MATCH); matcher.addURI("com.demo.sqlite.provider", "person", PERSON); // 添加一个可以匹配的Uri matcher.addURI("com.demo.sqlite.provider", "person/#", PERSON_ID); helper = new DBOpenHelper(getContext()); return true; } @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { switch (matcher.match(uri)) { // 对Uri进行匹配 case PERSON_ID: String idSelection = "id = " + ContentUris.parseId(uri); // Converts the last path segment to a long. // 注意此处字符串拼装 selection = selection == null ? idSelection : idSelection + " AND " + selection; case PERSON: SQLiteDatabase db = helper.getReadableDatabase(); return db.query("person", projection, selection, selectionArgs, null, null, sortOrder); default: throw new IllegalArgumentException("No Match Uri " + uri); } } @Override public Uri insert(Uri uri, ContentValues values) { switch (matcher.match(uri)) { case PERSON: SQLiteDatabase db = helper.getWritableDatabase(); long id = db.insert("person", null, values); // 使用 db.insert() 方法插入数据,返回 id // 而 db.exceSQL(sql)方式插入数据,返回 void // return Uri.parse("content://com.demo.sqlite.provider/person/" + id); // 与下句效果相同 return ContentUris.withAppendedId(uri, id); // Appends the given ID to the end of the path. default: throw new IllegalArgumentException("No Match Uri " + uri); } } @Override public int delete(Uri uri, String selection, String[] selectionArgs) { switch (matcher.match(uri)) { case PERSON_ID: long id = ContentUris.parseId(uri); selection = selection == null ? "id = " + id : "id = " +id + " AND " +selection; case PERSON: SQLiteDatabase db = helper.getWritableDatabase(); // return : The number of rows affected return db.delete("person", selection, selectionArgs); default: throw new IllegalArgumentException("No Match Uri " + uri); } } @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { switch (matcher.match(uri)) { case PERSON_ID: long id = ContentUris.parseId(uri); selection = selection == null ? "id = " + id : "id = " + id + " AND " + selection; case PERSON: SQLiteDatabase db = helper.getWritableDatabase(); // @return the number of rows affected return db.update("person", values, selection, selectionArgs); default: throw new IllegalArgumentException("No Match Uri " + uri); } } @Override public String getType(Uri uri) { switch (matcher.match(uri)) { case PERSON_ID: return "vnd.android.cursor.item/person"; case PERSON: return "vnd.android.cursor.dir/person"; default: throw new IllegalArgumentException("No Match Uri " + uri); } }
1.5. 访问内容提供者
Ÿ 通过Context获得ContentResolver对象
Ÿ 调用ContentResolver对象的方法即可访问内容提供者
private static final String TAG = "ProviderTest"; // 查询 id = 36 public void testQuery1() { // 通过 ContentResolver 调用 ContentProvider 提供的方法 ContentResolver resolver = getContext().getContentResolver(); Uri uri = Uri.parse("content://com.demo.sqlite.provider/person"); Cursor c = resolver.query(uri, new String[] { "id", "name", "balance" }, "id = ?", new String[] { "36" }, null); if (c.moveToNext()) { Person person = new Person(c.getInt(0), c.getString(1), c.getInt(2)); Logger.i(TAG, person.toString()); } } // 查询所有 person public void testQuery2() { // 通过 ContentResolver 调用 ContentProvider 提供的方法 ContentResolver resolver = getContext().getContentResolver(); Uri uri = Uri.parse("content://com.demo.sqlite.provider/person"); Cursor c = resolver.query(uri, null, null, null, null); while (c.moveToNext()) { Person person = new Person(c.getInt(0), c.getString(1), c.getInt(2)); Logger.i(TAG, person.toString()); } } // 通过附带 id 查询 person public void testQuery3() { // 通过 ContentResolver 调用 ContentProvider 提供的方法 ContentResolver resolver = getContext().getContentResolver(); // Uri Uri uri = Uri.parse("content://com.demo.sqlite.provider/person/55"); Cursor c = resolver.query(uri, null, "name = ?", new String[] { "Ashia_54" }, null); while (c.moveToNext()) { Person person = new Person(c.getInt(0), c.getString(1), c.getInt(2)); Logger.i(TAG, person.toString()); } } public void testInsert() { ContentResolver resolver = getContext().getContentResolver(); Uri uri = Uri.parse("content://com.demo.sqlite.provider/person"); ContentValues values = new ContentValues(); Person person = new Person("another Person uri insert", 7000); values.put("name", person.getName()); values.put("balance", person.getBalance()); Uri reUri = resolver.insert(uri, values); Cursor c = resolver.query(reUri, null, null, null, null); if (c.moveToNext()) { Person rePerson = new Person(c.getInt(0), c.getString(1), c.getInt(2)); Logger.i(TAG, rePerson.toString()); } } public void testDelete() { // ContentResolver :This class provides applications access to the content model. ContentResolver resolver = getContext().getContentResolver(); Uri url = Uri.parse("content://com.demo.sqlite.provider/person/121"); // 忘记加 = ?, 异常如下 // android.database.sqlite.SQLiteException: bind or column index out of range long id = resolver.delete(url, "name = ?", new String[] {"zhangsan"}); Logger.i(TAG, id + ""); id = resolver.delete(url, null, null); Logger.i(TAG, id + ""); } public void testDeleteAll() { ContentResolver resolver = getContext().getContentResolver(); Uri url = Uri.parse("content://com.demo.sqlite.provider/person"); int deleteNum = resolver.delete(url, null, null); Logger.i(TAG, deleteNum + ""); } public void testUpdate() { ContentResolver resolver = getContext().getContentResolver(); Uri uri = Uri.parse("content://com.demo.sqlite.provider/person/122"); ContentValues values = new ContentValues(); values.put("balance", 8000); int update = resolver.update(uri, values, "balance = ?", new String[] {"9000"}); Logger.i(TAG, update + ""); } public void testUpdateById() { ContentResolver resolver = getContext().getContentResolver(); ContentValues values = new ContentValues(); values.put("name", "new name"); values.put("balance", 7000); values.put("id", 2); Uri uri = Uri.parse("content://com.demo.sqlite.provider/person/123"); int update = resolver.update(uri, values, null, null); Logger.i(TAG, update + ""); } // Uri写错,异常 // java.lang.IllegalArgumentException: Unknown URI // 主键 id 重复,异常 // android.database.sqlite.SQLiteConstraintException public void testGetType() { ContentResolver resolver = getContext().getContentResolver(); Uri uri = Uri.parse("content://com.demo.sqlite.provider/person/1"); Logger.i(TAG, resolver.getType(uri)); uri = Uri.parse("content://com.demo.sqlite.provider/person"); Logger.i(TAG, resolver.getType(uri)); }