清单文件中的provider
ContentProvider,内容提供者,Android四大组件之一。主要作用,提供进程间数据共享和交互,为存储和获取数据提供统一的接口。ContentProvider底层采用Binder机制。
ContentProvider的数据共享主要用于操作本地数据库,外界通过ContentResolver提供的Api操作由ContentProvider共享的数据库的。
1. 在清单文件中声明需要共享的ContentProvider
复制代码
2. 统一资源标识符(URI)
URI 英文全写,Uniform Resource Identifier,可以通过URI来标识ContentProvider,外界通过URI找到对应的ContentProvider操作数据库。
自定义URI:
content://cn.scu.myprovider/User/1复制代码
content://
scheme主题:标识是ContentProvider的URI的前缀(Android系统规定)- authority: ContentProvider唯一标识符,URI中的host
- 表名:User
- 记录(ID): 表中某条记录
3. ContentProvider类
通过数据库组织数据,进程间共享数据的本质是:添加,删除,获取,更新,ContentProvider核心方法也是这4个操作。 外部进程在调用Content Provider方法的时候,是通过运行在ContentProvider进程的Binder线程池中,存在多线程并发的问题,需要线程同步。
- 若ContentProvider的数据存储方式是使用SQLite & 一个,则不需要,因为SQLite内部实现好了线程同步,若是多个SQLite则需要,因为SQL对象之间无法进行线程同步
- 若ContentProvider的数据存储方式是内存,则需要自己实现线程同步
ContentProvider 创建后,打开ContentProvider所在进程后,系统会调用ContentProvider的onCreate()方法,该方法运行在主线程。
3.1 ContentProvider 辅助类
三个辅助类:ContentUris,UriMatcher, ContentObserver
ContentUris类
ContentUris 主要用于 操作 URI。添加id和解析id
// withAppendedId()作用:向URI追加一个idUri uri = Uri.parse("content://cn.scu.myprovider/user") Uri resultUri = ContentUris.withAppendedId(uri, 7); // 最终生成后的Uri为:content://cn.scu.myprovider/user/7// parseId()作用:从URL中获取IDUri uri = Uri.parse("content://cn.scu.myprovider/user/7") long personid = ContentUris.parseId(uri); //获取的结果为:7复制代码
UriMatcher类
主要有两个作用:
- 在ContentProvider 中注册URI
- 根据 URI 匹配 ContentProvider 中对应的数据表
//1.初始化UriMatcher对象 UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH); //2.注册URI int URI_CODE_a = 1; int URI_CODE_b = 2; matcher.addURI("cn.scu.myprovider", "user1", URI_CODE_a); matcher.addURI("cn.scu.myprovider", "user2", URI_CODE_b); //3.根据URI 匹配 URI_CODE,从而匹配ContentProvider中相应的资源 @Override public String getType(Uri uri) { Uri uri = Uri.parse(" content://cn.scu.myprovider/user1"); switch(matcher.match(uri)){ // 根据URI匹配的返回码是URI_CODE_a // 即matcher.match(uri) == URI_CODE_a case URI_CODE_a: return tableNameUser1; // 如果根据URI匹配的返回码是URI_CODE_a,则返回ContentProvider中的名为tableNameUser1的表 case URI_CODE_b: return tableNameUser2; // 如果根据URI匹配的返回码是URI_CODE_b,则返回ContentProvider中的名为tableNameUser2的表 } 复制代码
ContentObserver类
内容观察者,观察 Uri引起 ContentProvider 中的数据变化 & 通知外界(即访问该数据访问者) 。当ContentProvider 中的数据发生变化(增、删 & 改)时,就会触发该 ContentObserver类
//1. 注册内容观察者ContentObservergetContentResolver().registerContentObserver(uri);//2. 当该URI的ContentProvider数据发生变化时,通知外界(即访问该ContentProvider数据的访问者) public class UserContentProvider extends ContentProvider { public Uri insert(Uri uri, ContentValues values) { db.insert("user", "userid", values); getContext().getContentResolver().notifyChange(uri, null); // 通知访问者 } //3. 解除观察者 getContentResolver().unregisterContentObserver(uri); 复制代码
4. ContentResolver类
通过URI 操作不同的ContentProvider中的数据。操作的方法与ContentProvider中方法相同,也是对数据库的增,删,查,改。
// 使用ContentResolver前,需要先获取ContentResolver// 可通过在所有继承Context的类中 通过调用getContentResolver()来获得ContentResolverContentResolver resolver = getContentResolver(); // 设置ContentProvider的URIUri uri = Uri.parse("content://cn.scu.myprovider/user"); // 根据URI 操作 ContentProvider中的数据// 此处是获取ContentProvider中 user表的所有记录 Cursor cursor = resolver.query(uri, null, null, null, "userid desc"); 复制代码