1.6 清单文件中的provider
清单文件中的provider
ContentProvider,内容提供者,Android四大组件之一。主要作用,提供进程间数据共享和交互,为存储和获取数据提供统一的接口。ContentProvider底层采用Binder机制。
ContentProvider的数据共享主要用于操作本地数据库,外界通过ContentResolver提供的Api操作由ContentProvider共享的数据库的。
1. 在清单文件中声明需要共享的ContentProvider
<provider
android:name=".module.contentprovider.MyProvider"
//Authority(授权信息) ContentProvider唯一标识符
android:authorities="cn.scu.myprovider"
android:exported="true"
android:permission="scut.carson_ho.PROVIDER" />
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追加一个id
Uri uri = Uri.parse("content://cn.scu.myprovider/user")
Uri resultUri = ContentUris.withAppendedId(uri, 7);
// 最终生成后的Uri为:content://cn.scu.myprovider/user/7
// parseId()作用:从URL中获取ID
Uri 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. 注册内容观察者ContentObserver
getContentResolver().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()来获得ContentResolver
ContentResolver resolver = getContentResolver();
// 设置ContentProvider的URI
Uri uri = Uri.parse("content://cn.scu.myprovider/user");
// 根据URI 操作 ContentProvider中的数据
// 此处是获取ContentProvider中 user表的所有记录
Cursor cursor = resolver.query(uri, null, null, null, "userid desc");