Android四大组件-内容提供者
2017-06-07 16:20
841 查看
1、特点
①、可以将应用中的数据对外进行共享;
②、数据访问方式统一,不必针对不同数据类型采取不同的访问策略;
③、内容提供者将数据封装,只暴露出我们希望提供给其他程序的数据(这点有点类似Javabeans);
④、内容提供者中数据更改可被监听;
2、创建内容提供者
定义类继承ContentProvider,根据需要重写其内容方法(6个方法):
onCreate() 创建内容提供者时,会调用这个方法,完成一些初始化操作;
crud相应的4个方法 用于对外提供CRUD操作;
getType() 返回当前Url所代表数据的MIME类型:
返回的是单条记录:以vnd.android.cursor.item/ 开头,如:vnd.android.cursor.item/person
返回的是多条记录:以vnd.android.cursor.dir/ 开头,如:vnd.android.cursor.dir/person
在清单文件的节点下进行配置,标签中需要指定name、authorities、exported属性
name: 为全类名;
authorities: 是访问Provider时的路径,要唯一;
exported: 用于指示该服务是否能够被其他应用程序组件调用或跟它交互
URI代表要操作的数据,由scheme、authorites、path三部分组成:
content://com.itheima.sqlite.provider/person
scheme: 固定为content,代表访问内容提供者;
authorites: 节点中的authorites属性;
path: 程序定义的路径,可根据业务逻辑定义;
操作 URI的UriMather与ContentUris工具类:
当程序调用CRUD方法时会传入Uri
UriMatcher:表示URI匹配器,可用于添加Uri匹配模式,与匹配Uri(见下代码);
ContentUris:用于操作Uri路径后面的ID部分,2个重要的方法:
1. withAppendedId(uri, id) 为路径加上ID部分;
2. parseId(uri) 用于从路径中获取ID部分;
示例代码(内容提供者类):
5、区别Provider/Resolver/Observer
1)ContentProvider:内容提供者
把一个应用程序的私有数据(如数据库)信息暴露给别的应用程序,让别的应用程序可以访问;
在数据库中有对应的增删改查的方法,如果要让别的应用程序访问,需要有一个路径uri:
通过content:// 路径对外暴露,uri写法:content://主机名/表名
2)ContentResolver:内容解析者
根据内容提供者的路径,对数据进行操作(crud);
3)ContentObserver:内容观察者
可以理解成android系统包装好的回调,数据发送变化时,会执行回调中的方法;
ContentResolver发送通知,ContentObserver监听通知;
当A的数据发生变化的时候,A就会显示的通知一个内容观察者,不指定观察者,就会发消息给一个路径
①、可以将应用中的数据对外进行共享;
②、数据访问方式统一,不必针对不同数据类型采取不同的访问策略;
③、内容提供者将数据封装,只暴露出我们希望提供给其他程序的数据(这点有点类似Javabeans);
④、内容提供者中数据更改可被监听;
2、创建内容提供者
定义类继承ContentProvider,根据需要重写其内容方法(6个方法):
onCreate() 创建内容提供者时,会调用这个方法,完成一些初始化操作;
crud相应的4个方法 用于对外提供CRUD操作;
getType() 返回当前Url所代表数据的MIME类型:
返回的是单条记录:以vnd.android.cursor.item/ 开头,如:vnd.android.cursor.item/person
返回的是多条记录:以vnd.android.cursor.dir/ 开头,如:vnd.android.cursor.dir/person
在清单文件的节点下进行配置,标签中需要指定name、authorities、exported属性
name: 为全类名;
authorities: 是访问Provider时的路径,要唯一;
exported: 用于指示该服务是否能够被其他应用程序组件调用或跟它交互
URI代表要操作的数据,由scheme、authorites、path三部分组成:
content://com.itheima.sqlite.provider/person
scheme: 固定为content,代表访问内容提供者;
authorites: 节点中的authorites属性;
path: 程序定义的路径,可根据业务逻辑定义;
操作 URI的UriMather与ContentUris工具类:
当程序调用CRUD方法时会传入Uri
UriMatcher:表示URI匹配器,可用于添加Uri匹配模式,与匹配Uri(见下代码);
ContentUris:用于操作Uri路径后面的ID部分,2个重要的方法:
1. withAppendedId(uri, id) 为路径加上ID部分;
2. parseId(uri) 用于从路径中获取ID部分;
示例代码(内容提供者类):
public class HeimaProvider extends ContentProvider { private static final int PERSON = 1; // 匹配码 private static final int STUDENT = 2; // 匹配码 private static final int PERSON_ID = 3; // 匹配码 private MyHelper helper; /** Uri匹配器 */ private UriMatcher uriMatcher = new UriMatcher(UriMatcher.NO_MATCH); @Override public boolean onCreate() { System.out.println("onCreate..."); helper = new MyHelper(getContext()); // == 添加 uri 匹配模式, 设置匹配码(参数3) Uri如果匹配就会返回相应的匹配码 == uriMatcher.addURI("com.itheima.sqlite.provider", "person", PERSON); uriMatcher.addURI("com.itheima.sqlite.provider", "#", PERSON_ID); // #表示匹配数字,*表示匹配文本 uriMatcher.addURI("com.itheima.sqlite.provider", "student", STUDENT); return true; } @Override public Uri insert(Uri uri, ContentValues values) { SQLiteDatabase db = helper.getWritableDatabase(); switch (uriMatcher.match(uri)) { // 匹配uri case PERSON: long id = db.insert("person", "id", values); db.close(); return ContentUris.withAppendedId(uri, id); // 在原uri上拼上id,生成新的uri并返回; case STUDENT: long insert = db.insert("student", "id", values); System.out.println("数据文件中,没有student表,也不会报错"); db.close(); return ContentUris.withAppendedId(uri, insert); // 为路径上,加上ID default: throw new IllegalArgumentException(String.format("Uri:%s 不是合法的uri地址", uri)); } } @Override public int delete(Uri uri, String selection, String[] selectionArgs) { SQLiteDatabase db = helper.getWritableDatabase(); switch (uriMatcher.match(uri)) { // 匹配uri case PERSON_ID: long parseId = ContentUris.parseId(uri); // 获取传过来的ID值 selection = "id=?"; // 设置查询条件 selectionArgs = new String[] { parseId + "" }; // 查询条件值 case PERSON: int delete = db.delete("person", selection, selectionArgs); db.close(); return delete; default: throw new IllegalArgumentException(String.format("Uri:%s 不是合法的uri地址", uri)); } } @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { SQLiteDatabase db = helper.getWritableDatabase(); switch (uriMatcher.match(uri)) { case PERSON_ID: long parseId = ContentUris.parseId(uri); // 获取传过来的ID值 selection = "id=?"; // 设置查询条件 4000 selectionArgs = new String[] { parseId + "" }; // 查询条件值 case PERSON: int update = db.update("person", values, selection, selectionArgs); db.close(); return update; default: throw new IllegalArgumentException(String.format("Uri:%s 不是合法的uri地址", uri)); } } @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { SQLiteDatabase db = helper.getWritableDatabase(); switch (uriMatcher.match(uri)) { case PERSON_ID: // == 根据ID查询 == long parseId = ContentUris.parseId(uri); // 获取传过来的ID值 selection = "id=?"; // 设置查询条件 selectionArgs = new String[] { parseId + "" }; // 查询条件值 case PERSON: Cursor cursor = db.query("person", projection, selection, selectionArgs, null, null, sortOrder); // == 注意:此处的 db与cursor不能关闭 == return cursor; default: throw new IllegalArgumentException(String.format("Uri:%s 不是合法的uri地址", uri)); } } // 返回传入URI的类型,可用于测试URI是否正确 @Override public String getType(Uri uri) { switch (uriMatcher.match(uri)) { case PERSON_ID: return "vnd.android.cursor.item/person"; // 表示单条person记录 case PERSON: return "vnd.android.cursor.dir/person"; // 表单多个person记录 default: return null; } } } 清单中的配置: <provider android:exported="true" android:name="com.itheima.sqlite.provider.HeimaProvider" android:authorities="com.itheima.sqlite.provider" /> authorities 可以配置成如下形式(系统联系人的): android:authorities="contacts;com.android.contacts" “;” 表示的是可使用 contacts, 与 com.android.contacts 3、内容解析者ContentResolver 通过Context获得ContentResolver内容访问者对象(内容提供者的解析器对象); 调用ContentResolver对象的方法即可访问内容提供者 测试类代码: public class HeimaProviderTest extends AndroidTestCase { /** 测试添加数据 */ public void testInsert() { ContentResolver resolver = this.getContext().getContentResolver(); Uri uri = Uri.parse("content://com.itheima.sqlite.provider/person"); ContentValues values = new ContentValues(); values.put("name", "小翼"); values.put("balance", 13000); Uri insert = resolver.insert(uri, values); // 获取返回的uri,如:content://com.itheima.sqlite.provider/7 System.out.println(insert); } /** 测试删除 */ public void testRemove() { ContentResolver resolver = this.getContext().getContentResolver(); Uri uri = Uri.parse("content://com.itheima.sqlite.provider/person"); int count = resolver.delete(uri, "id=?", new String[] { 3 + "" }); System.out.println("删除了" + count + "行"); } /** 测试更新 */ public void testUpdate() { ContentResolver resolver = this.getContext().getContentResolver(); Uri uri = Uri.parse("content://com.itheima.sqlite.provider/person"); ContentValues values = new ContentValues(); values.put("name", "小赵 update"); values.put("balance", 56789); int update = resolver.update(uri, values, "id=?", new String[] { 6 + "" }); System.out.println("更新了" + update + "行"); } /** 测试查询 */ public void testQueryOne() { ContentResolver resolver = this.getContext().getContentResolver(); Uri uri = Uri.parse("content://com.itheima.sqlite.provider/person"); Cursor c = resolver.query(uri, new String[] { "name", "balance" }, "id=?", new String[] { 101 + "" }, null); if (c.moveToNext()) { System.out.print(c.getString(0)); System.out.println(" " + c.getInt(1)); } c.close(); } /**测试查询全部 */ public void testQueryAll() { ContentResolver resolver = this.getContext().getContentResolver(); Uri uri = Uri.parse("content://com.itheima.sqlite.provider/person"); Cursor c = resolver.query(uri, new String[] { "id", "name", "balance" }, null, null, "name desc"); while (c.moveToNext()) { System.out.println(c.getInt(0) + ", " + c.getString(1) + ", " + c.getInt(2)); } c.close(); } /** 测试查询一条 */ public void testQueryOneWithUriId() { ContentResolver resolver = this.getContext().getContentResolver(); Uri uri = Uri.parse("content://com.itheima.sqlite.provider/3"); // 查询ID为3的记录 Cursor c = resolver.query(uri, new String[] { "id", "name", "balance" }, null, null, null); if (c.moveToNext()) { System.out.println(c.getInt(0) + ", " + c.getString(1) + ", " + c.getInt(2)); } c.close(); } /** 测试获取内容提供者的返回类型 */ public void testGetType() { ContentResolver resolver = this.getContext().getContentResolver(); System.out.println(resolver.getType(Uri.parse("content://com.itheima.sqlite.provider/2"))); System.out.println(resolver.getType(Uri.parse("content://com.itheima.sqlite.provider/person"))); } } 4、监听内容提供者的数据变化 在内容提供者中可以通知其他程序数据发生变化 通过Context的getContentResolver()方法获取ContentResolver 调用其notifyChange()方法发送数据修改通知,发送到系统的公共内存(消息信箱中) 在其他程序中可以通过ContentObserver监听数据变化 通过Context的getContentResolver()方法获取ContentResolver 调用其registerContentObserver()方法指定对某个Uri注册ContentObserver 自定义ContentObserver,重写onChange()方法获取数据 示例代码(发通知部分): public int delete(Uri uri, String selection, String[] selectionArgs) { SQLiteDatabase db = helper.getWritableDatabase(); int delete = db.delete("person", selection, selectionArgs); // == 通过内容访问者对象ContentResolve 发通知给所有的Observer == getContext().getContentResolver().notifyChange(uri, null); db.close(); return delete; } } 监听部分: // 注册内容观察者事件 private void initRegisterContentObserver() { Uri uri = Uri.parse("content://com.itheima.sqlite.provider"); // 监听的URI // == 第2个参数:true表示监听的uri的后代都可以监听到 == getContentResolver().registerContentObserver(uri, true, new ContentObserver(new Handler()) { public void onChange(boolean selfChange) { // 接到通知就执行 personList = personDao.queryAll(); ((BaseAdapter) personListView.getAdapter()).notifyDataSetChanged(); } }); }
5、区别Provider/Resolver/Observer
1)ContentProvider:内容提供者
把一个应用程序的私有数据(如数据库)信息暴露给别的应用程序,让别的应用程序可以访问;
在数据库中有对应的增删改查的方法,如果要让别的应用程序访问,需要有一个路径uri:
通过content:// 路径对外暴露,uri写法:content://主机名/表名
2)ContentResolver:内容解析者
根据内容提供者的路径,对数据进行操作(crud);
3)ContentObserver:内容观察者
可以理解成android系统包装好的回调,数据发送变化时,会执行回调中的方法;
ContentResolver发送通知,ContentObserver监听通知;
当A的数据发生变化的时候,A就会显示的通知一个内容观察者,不指定观察者,就会发消息给一个路径
相关文章推荐
- Android四大组件之ContentProvider(内容提供者)01
- 【android学习】四大组件-Content Provider(内容提供者)
- Android基础之四大组件-ContentProvider(内容提供者)
- android四大组件之一内容提供者contentprovider
- Android四大组件之一之内容提供者ContentProvider
- Android四大组件之Content Provider(内容提供者)
- Android之四大组件之一-ContentProvider内容提供者的使用(二)
- Android四大组件之ContentProvide(内容提供者)
- Android——ContentProvide 内容提供者+四大组件之三
- Android四大组件之----内容提供者
- Android笔记---四大组件之Content Provider内容提供者详解
- Android四大组件之一ContentProvider(内容提供者)
- Android 四大组件之一 :ContentProvider内容提供者从入门到精通
- Android四大组件之内容提供者Content Provider总结
- Android四大组件-内容提供者
- Android之四大组件之一-Content Provider内容提供者的介绍(一)
- Android四大组件之内容提供者
- Android——ContentProvide 内容提供者+四大组件之三
- Android四大组件之ContentProvider(内容提供者)02
- Android四大组件之一ContentProvider内容提供者(继SQLite数据存储篇)