ContentProvider也是Android四大组件之一,它主要实现了不同应用之间的信息、数据的共享。ContentProvider就像一个中间人,当我们的应用想去访问其他应用的数据库或其他应用访问我们的数据库时,都需要通过ContentProvider。
一、如何创建一个ContentProvider
1定义内容提供者 定义一个类继承contentProvider
2在清单文件里面配置一下
3 定义一个urimatcher,通过UriMatcher来确定哪个uri请求执行哪项操作
4写一个静态代码块 添加匹配规则
5按照我们添加的匹配规则 暴露想暴露的方法
然后其他应用就可以通过内容解析者(ContentResolver)去获取内容提供者中暴露出来的方法了。
public class AccountProvider extends ContentProvider {
//[1]定一个一个uri路径匹配器
private static final UriMatcher sURIMatcher = new UriMatcher(UriMatcher.NO_MATCH);
private static final int QUERYSUCESS = 0; //ctrl+shift+X 变大写 小写加y
private static final int INSERTSUCESS = 1;
private static final int UPDATESUCESS = 2;
private static final int DELETESUCESS = 3;
private MyOpenHelper myOpenHelper;
//[2]创建一个静态代码块 在这个里面添加 uri
static{
/**
* authority 注意: 和清单文件里面定义的一样
*
*/
sURIMatcher.addURI("com.example.lbj.provider", "query", QUERYSUCESS);
sURIMatcher.addURI("com.example.lbj.provider", "insert", INSERTSUCESS);
sURIMatcher.addURI("com.example.lbj.provider", "update", UPDATESUCESS);
sURIMatcher.addURI("com.example.lbj.provider", "delete", DELETESUCESS);
}
//当内容提供者初始化 会执行此方法
@Override
public boolean onCreate() {
//[3]初始化 myopenHelpler 对象 就可以获取到sqlitedatabases对象 我们就可以操作数据库
myOpenHelper = new MyOpenHelper(getContext());
return false;
}
//这个方法对外暴露的
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
int code = sURIMatcher.match(uri);
if (code ==QUERYSUCESS ) {
//说明路径匹配成功
SQLiteDatabase db = myOpenHelper.getReadableDatabase();
//调用query方法
Cursor cursor = db.query("info", projection, selection, selectionArgs, null, null, sortOrder);
//发送一条消息 说明说明数据库被操作了
getContext().getContentResolver().notifyChange(uri, null);
// db.close();
//小细节 ☆ 这个cursor不能关
return cursor;
}else{
//说明路径不匹配
// return null;
throw new IllegalArgumentException("uri路径不匹配 请检测路径");
}
}
@Override
public String getType(Uri uri) {
return null;
}
@Override
public Uri insert(Uri uri, ContentValues values) {
int code = sURIMatcher.match(uri);
if (code == INSERTSUCESS) {
//说明路径匹配成功
SQLiteDatabase db = myOpenHelper.getReadableDatabase();
long insert = db.insert("info", null, values);
Uri uri2 = Uri.parse("com.hahaheheheihei/"+insert);
if (insert>0) {
//发送一条消息 说明说明数据库被操作了
getContext().getContentResolver().notifyChange(uri, null);
}
db.close();//关闭数据库
return uri2;
}else {
throw new IllegalArgumentException("uri路径不匹配 请检测路径");
}
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
int code = sURIMatcher.match(uri);
if (code == DELETESUCESS) {
//匹配成功
SQLiteDatabase db = myOpenHelper.getReadableDatabase();
//代表影响的行数
int delete = db.delete("info", selection, selectionArgs);
if (delete>0) {
//发送一条消息 说明说明数据库被操作了
getContext().getContentResolver().notifyChange(uri, null);
}
return delete;
}
return 0;
}
@Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
int code = sURIMatcher.match(uri);
if (code == UPDATESUCESS) {
//路径匹配成功
SQLiteDatabase db = myOpenHelper.getWritableDatabase();
//代表影响的行数
int update = db.update("info", values, selection, selectionArgs);
if(update>0){
//发送一条消息 说明说明数据库被操作了
getContext().getContentResolver().notifyChange(uri, null);
}
return update;
}else{
throw new IllegalArgumentException("uri路径不匹配 请检测路径");
}
}
}
除了onCreate()和getType()方法外,其他的均为CRUD操作,这些方法中,Uri(
统一资源标志符)参数为与ContentProvider匹配的请求Uri。
真正的开发中我们很少会自己去定义一个ContentProvider将应用的数据暴露出去(因为暴露出去也很少有人会访问),更多的是使用内容解析者去访问系统或其他应用的ContentProvider,下面就来看一下ContentResolver。
二‘ContentResolver内容解析者
在使用ContentProvider通过定义一个对外开放的统一的接口来实现共享数据后,我们并不会直接调用这些方法,而是使用ContentResolver内容解析者去调用这些方法。通常我们通过一个getContentResolver()方法来获取ContentResolver对象,ContentResolver中也包含了增删查改四个方法,对应内容提供者的方法,如下所示:
public Uri insert(Uri uri, ContentValues values) 该方法用于往ContentProvider添加数据。
public int delete(Uri uri, String selection, String[] selectionArgs) 该方法用于从ContentProvider删除数据。
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) 该方法用于更新ContentProvider中的数据。
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) 该方法用于从ContentProvider中获取数据。
下面是一段读取手机联系人的示例代码:
ContentObserver内容观察者通常用来观察ContentProvider(数据库)的变化,然后通知主线程数据库的内容发生了改变。内容观察者不属于四大组件,所以不需要去清单文件中配置,直接实现一个类继承自ContentObserver就可以了。下面是定义一个ContentObserver的代码:
下面是一段读取手机联系人的示例代码:
public static List<Contact> queryContacts(Context context){
//[0]创建一个集合
List<Contact> contactLists = new ArrayList<Contact>();
//[1]先查询row_contacts表 的contact_id列 我们就知道一共有几条联系人
Uri uri = Uri.parse("content://com.android.contacts/raw_contacts");
Uri dataUri = Uri.parse("content://com.android.contacts/data");
Cursor cursor = context.getContentResolver().query(uri,new String[]{"contact_id"} , null, null, null);
while(cursor.moveToNext()){
String contact_id = cursor.getString(0);
if (contact_id!=null) {
//创建javabean对象
Contact contact = new Contact();
contact.setId(contact_id);
System.out.println("contact_id:"+contact_id);
//[2]根据contact_id去查询data表 查询data1列和mimetype_id
//我们在查询data表的时候 其实查询的是view_data的视图
Cursor dataCursor = context.getContentResolver().query(dataUri, new String[]{"data1","mimetype"}, "raw_contact_id=?", new String[]{contact_id}, null);
while(dataCursor.moveToNext()){
String data1 = dataCursor.getString(0);
String mimetype = dataCursor.getString(1);
//[3]根据mimetype 区分data1列的数据类型
if ("vnd.android.cursor.item/name".equals(mimetype)) {
contact.setName(data1);
}else if ("vnd.android.cursor.item/phone_v2".equals(mimetype)) {
contact.setPhone(data1);
}else if ("vnd.android.cursor.item/email_v2".equals(mimetype)) {
contact.setEmail(data1);
}
}
//把javabean对象加入到集合中
contactLists.add(contact);
}
}
return contactLists;
}
三、ContentObserver内容观察者
ContentObserver内容观察者通常用来观察ContentProvider(数据库)的变化,然后通知主线程数据库的内容发生了改变。内容观察者不属于四大组件,所以不需要去清单文件中配置,直接实现一个类继承自ContentObserver就可以了。下面是定义一个ContentObserver的代码:
//定义内容观察者
private class MyContentObserver extends ContentObserver{
public MyContentObserver(Handler handler) {
super(handler);
}
//当我们观察的uri发生改变的时候调用
@Override
public void onChange(boolean selfChange) {
System.out.println("哈哈 数据库被操作了 ");
super.onChange(selfChange);
}
}
定义好内容观察者后就可以在主线程中注册内容观察者了,
//注册内容观察者
Uri uri = Uri.parse("content://.../");//要观察的内容提供者的Uri
//false 观察的uri 必须是一个确切的uri 如果是true 模糊匹配只提供部分Uri就可以
getContentResolver().registerContentObserver(uri, true, new MyContentObserver(new Handler()));
这样当数据库发生改变时就可以监控到数据库的变化了。以上就是内容提供者的相关内容,如有错误,请多多指教