Content Provider,内容供给源,简称供给源或Provier,Android四类组件之一,用来在不同的application之间共享数据,通常包含两个部分,用别人或被别人用,即调用别人application的Provider或为自己的application创建Provier给别人用。举例来说,系统自有电话薄application就对外提供了ContactsProvider,我们可以做个application通过ContactsProvider来得到系统电话簿的数据,如果自己的application需要向外共享数据时,需要建立自己的Provider,Provider可以理解为不同application之间的数据接口。
官网地址http://developer.android.com/guide/topics/providers/content-providers.html#basics
我们知道一个database包含很多个table,每个table包含多个column,每个table有记录数据。一个provider类似一个database,或.net中的dataset,内部也包含一个或多个table,每个table包含一个或多个column。
为了方便操作provider,系统采用uri的方式来操作数据,格式为:
<Standard_Prefix>://<authority>/<data_path>/<id>
例content ://com.android.contacts/data/phones
content://com.android.contacts/contacts
系统自带联系人uri为“content://com.android.contacts/contacts”,Content表示该Uri对应一个Content Provider,而不是http或ip,“com.android.contacts”对应authority,contacts为表名。联系人的电话薄uri为content://com.android.contacts/data/phones,phones为表名。如果带id则表示操作该id对应的数据。
· 读取Provider:
方法一:getContentResolver().query(uri, projection, selection, selectionArgs, sortOrder)
方法二:Activity.managedQuery(uri, projection, selection, selectionArgs, sortOrder)
Uri:表名
projection:列名称集合
selection:对应sql语句中的where
selectionArgs: selection中占位符“?”对应变量的参数值
sortOrder:对应order by 语句
这两个方法返回的是Cursor游标,相当于数据库中的游标,Cursor提供了moveToFirst()、moveToLast()、moveToNext()、moveToPrevious() 、moveToPosition(position)等方法来控制游标的移动,同时提供了getString(columnIndex)、getInt(columnIndex)等方法来读取值。
· 添加数据:
单个添加:getContentResolver().insert(url, values)
Uri:表名
Values:键值对,key为列名,value为值
该方法返回一个带id的uri,代表刚添加的数据项的uri
批量添加:getContentResolver().applyBatch(authority, operations)
返回值为添加的个数
· 修改数据:
getContentResolver().update(uri, values, where, selectionArgs)
· 删除数据:
getContentResolver().delete(url, where, selectionArgs)
返回删除的个数
可以从抽象类ContentProvider派生自己的类来实现自己的provider,在此过程中需要重载如下几个抽象方法:
· onCreate():在创建自定义provider时执行;
· query(uri,projection,selection,selectionArgs,sortOrder):查找数据,并返回含有数据信息的cursor对象。
· Insert(uri,values):向数据库插入一行新的记录,并返回对应的uri。
· Update(uri,values,where,selectionArgs):更新指定的数据内容。
· Delete(uri,where,selectionArgs):删除指定的数据。
· GetType(uri):返回uri的MIME类型。
注意建立完自己的provider后,不要忘记在AndroidManifest.xml文件中进行配置
当多个应用或同一个应用的不同操作来使用同一个provider时,就需要一种及时的通知机制。如下图,当应用2修改了provider的数据时,要及时的通知应用1。
图16-1 更新通知机制
通过在应用1中建立Observer观察者对象来完成对Provider中特定URI(表)的监视,当Provider数据变化时,观察者会自动被通知,然后观察者再通知注册的Resolver,Resolver通过观察者的URI,知道provider中哪个表被修改。
在应用2中,通过
Cursor.setNotificationUri(cr, uri);
getContentResolver().notifyChange(uri, observer);
方法发出通知,从而通知应用1中的观察者。
应用1中注册观察者通过
getContentResolver().registerContentObserver(uri, notifyForDescendents, observer);
方法来实现,注销时用
getContentResolver().unregisterContentObserver(observer);
方法来实现。
更改在观察者的onChange()方法捕获。
注意:观察者可以观察到URI的变化,但是URI并没有作为参数传递给观察者,所以当观察者观察一个表时,仅可以观察到表的改变,但是具体是增删改查哪种操作,或者哪个记录被操作无法观察到。
示例:
l 建立观察者
class ContactObserver extends ContentObserver {
Handler handler;
public ContactObserver(Handler handler) {
super(handler);
// TODO Auto-generated constructor stub
this.handler=handler;
}
public void onChange(boolean selfChange) {
Log.i("superContacts", "号码薄被修改了");
}
}
l Oncreate方法中注册观察者
Uri uri = ContactsContract.Contacts.CONTENT_URI;
observer = new ContactObserver(new Handler());
getContentResolver().registerContentObserver(uri, true, observer);
l Ondestroy方法中注销观察者
if(observer!=null) {
getContentResolver().unregisterContentObserver(observer);
}
Live folder(活动文件夹)