ContentProvider一般为存储和获取数据提供统一的接口,可以在不同的应用程序之间共享数据。
ContentProvider的好处和用途:
(1)ContentProvider提供了对底层数据存储方式的抽象。比如下图中,底层使用了SQLite数据库,在用了ContentProvider封装后,及时你把数据库换成MongoDB,也不会对上层数据使用层代码产生影响。
(2)Android框架中的一些类需要使用ContentProvider类型的数据。如果想让数据可以使用在SyncAdapter,Loader,CursorAdapter等类上,就需要为数据做一层ContentProvider封装。
(3)ContentProvider为应用间的数据交互提供了一个安全的环境。它允许你把自己的应用数据根据需求开放给其他应用进行增删改查,而不用担心直接开放数据库权限带来的安全问题。
ContentResolver是对ContentProvider的封装,用于对不同的ContentProvider进行操作。一般情况下一台手机中会有很多个Provider应用,如果要了解使用每个ContentProvider的实现会很麻烦,所以Android为我们提供了ContentResolver来同意管理于不同ContentProvider间的操作。
我们可以在所有继承Context的类中通过调用getContentResolver( )来获得ContentResolver。但是ContentResolver是如何来区别不同的ContentProvider的呢,这就需要涉及到URI(Uniform Resource Identifier)。
ContentProvider中的URI有固定格式,如下图:
Scheme:ContentProvider的scheme已经由Android规定好,即“content://”
Authority:主机名,也就是授权信息,用以区别不同的ContentProvider,外部调用者可以根据这个标识来找到它;
Path:表名,用以区分ContentProvider中不同的数据表;
Id:Id号,用以区别表中的不同数据
(1)创建一个类,并继承ContentProvider;
(2)在AndroidManifest中配置声明
(3)定义UriMatcher
private UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH); //创建一个URI匹配器,参数为不匹配时的返回值
在onCreate中使用matcher.addURI("authorities","path",code); //加入匹配的URI,如果匹配,则matcher.match(uri)返回code;
如果要匹配:content://authorities/path/数字 ,则matcher.addURI("authorites","path/#",code);
(4)重写增删改查等方法
onCreate():用于为操作数据做准备;
insert:插入数据,返回插入的记录所代表的URI;
update:更新数据,返回操作影响的记录行数;
delete:删除数据,返回操作影响的记录行数;
query:查询数据,返回Cursor;
getType:记录的类型,如果操作集合,则必须以vnd.android.cursor.dir开头,如果操作非集合,则必须以vnd.android.cursor.item开头,比如vnd.android.cursor.dir/person
(5)外部调用
ContentResolver resolver = this.getContext().getContentResolver();
resolver.insert();
resolver.update();
resolver.delete();
resolver.query();
步骤一:创建PersonProvider.java
public class PersonProvider extends ContentProvider {
private DatabaseHelper mHelper;
private SQLiteDatabase mDatabase;
private UriMatcher mMatcher = new UriMatcher(UriMatcher.NO_MATCH);
@Override
public boolean onCreate() {
mHelper = new DatabaseHelper(this.getContext());
//匹配:content://org.wxt.provides.personprovider/person,返回值为1
mMatcher.addURI("org.wxt.provides.personprovider","person",1);
//匹配:content://org.wxt.provides.personprovider/person/数字,返回值为2
mMatcher.addURI("org.wxt.provides.personprovider","person/#",2);
return true;
}
@Nullable
@Override
public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String
selection, @Nullable String[] selectionArgs, @Nullable String sortOrder) {
mDatabase = mHelper.getWritableDatabase();
switch (mMatcher.match(uri)){
case 1://查询所有记录
return mDatabase.query("person",projection,selection,selectionArgs,null,null,null);
case 2://查询特定记录
long id = ContentUris.parseId(uri);
String where = "id="+id;
if(selection!=null&&!"".equals(selection)){//因为selection可能还包含其他的where语句,需要再加上 "and id=?"
where = where+" and"+selection;
}
return mDatabase.query("person",projection,where,selectionArgs,null,null,null);
default:
throw new IllegalArgumentException("wrong uri");
}
}
/*
* 如果操作集合,则必须以vnd.android.cursor.dir开头
* 如果操作非集合,则必须以vnd.android.cursor.item开头
*/
@Override
public String getType(Uri uri) {
switch(mMatcher.match(uri)){
case 1:
return "vnd.android.cursor.dir/person";
case 2:
return "vnd.android.cursor.item/person";
default:
return null;
}
}
/**
*
* @param uri
* @param values 插入的数据
* @return
*/
@Nullable
@Override
public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {
mDatabase = mHelper.getWritableDatabase();
switch (mMatcher.match(uri)){
case 1:
long rowid = mDatabase.insert("person",null,values);
return ContentUris.withAppendedId(uri,rowid);
default:
throw new IllegalArgumentException("wrong uri");
}
return null;
}
@Override
public int delete(@NonNull Uri uri, @Nullable String selection, @Nullable String[]
selectionArgs) {
mDatabase = mHelper.getWritableDatabase();
switch (mMatcher.match(uri)){
case 1://删除全部记录
return mDatabase.delete("person",selection,selectionArgs);
case 2: //删除特定id的记录
long id = ContentUris.parseId(uri);
String where = " id"+id;
if(selection!=null&&!"".equals(selection)){
where +=" and"+selection;
}
return mDatabase.delete("person",where,selectionArgs);
default:
throw new IllegalArgumentException("wrong uri");
}
}
@Override
public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection, @Nullable String[] selectionArgs) {
mDatabase = mHelper.getWritableDatabase();
switch (mMatcher.match(uri)){
case 1://更新全部记录
return mDatabase.update("person",values,selection,selectionArgs);
case 2: //更新特定id的记录
long id = ContentUris.parseId(uri);
String where = " id"+id;
if(selection!=null&&!"".equals(selection)){
where +=" and"+selection;
}
return mDatabase.update("person",values,where,selectionArgs);
default:
throw new IllegalArgumentException("wrong uri");
}
}
}
步骤二:在AndroidManifest.xml注册
<manifest xmlns:android="http://schemas.android.com/apk/res/android";
package="com.example.administrator.myapplication">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
intent-filter>
activity>
<provider
android:authorities="org.wxt.provides.personprovider"
android:name=".PersonProvider"/>
application>
manifest>
步骤三:测试类调用 ContentProviderTest.java
public class ContentProviderTest extends AndroidTestCase {
public void testInsert()throws Exception{
Uri uri = Uri.parse("content://org.wxt.provides.personprovider/person");
ContentResolver resolver = this.getContext().getContentResolver();
ContentValues contentValues = new ContentValues();
contentValues.put("name","wxt");
contentValues.put("age",16);
resolver.insert(uri,contentValues);
}
public void testUpdate()throws Exception{
Uri uri = Uri.parse("content://org.wxt.provides.personprovider/person/5");
ContentResolver resolver = this.getContext().getContentResolver();
ContentValues contentValues = new ContentValues();
contentValues.put("name","wxt");
contentValues.put("age",16);
resolver.update(uri,contentValues,null,null);
}
public void testDelete()throws Exception{
Uri uri = Uri.parse("content://org.wxt.provides.personprovider/person/5");
ContentResolver resolver = this.getContext().getContentResolver();
resolver.delete(uri,null,null);
}
public void testQuery()throws Exception{
Uri uri = Uri.parse("content://org.wxt.provides.personprovider/person");
ContentResolver resolver = this.getContext().getContentResolver();
Cursor cursor = resolver.query(uri,null,null,null);
while (cursor.moveToNext()){
int id = cursor.getInt(cursor.getColumnIndex("id"));
String name =cursor.getString(cursor.getColumnIndex("name"));
int age = cursor.getInt(cursor.getColumnIndex("age"));
Person person = new Person(id ,name,age);
}
}
}