简介
上一篇博客已经介绍了Android原生数据库的使用,本篇博客就来记录Android的四大组件之一的内容提供者(ContentProvider),ContentProvider主要用于不同应用之间实现数据共享的功能,Android系统也提供对应的接口供应用程序读取数据,比如多媒体、联系人、短信等,它的数据源不单单是数据库,还有可能是XML、文件、网络等;
使用
在AndroidManifest注册
在Android文件AndroidManifest.xml注册
authorities:访问表的主机地址;
exported:是否允许对外应用程序访问,true允许,false不允许,默认false;
<!--给内容提供者提供定义一个uri,一般建议使用包名+类名,以供其它程序调用 -->
<provider
android:name="com.dream.contentprovider.provider.PersonProvider"
android:authorities="com.dream.contentprovider"
android:exported="true"/>
继承ContentProvider
Android系统为我们提供ContentProvider类,我们继承这个类实现onCreate()、getType()、insert()、delete()、update()、query();
onCreate():内容提供者初始化的时候调用,一般这里执行数据库创建、升级操作。
getType():根据给定的Uri返回一个MIME类型的数据。
insert():Uri表示需要操作哪张表,ContentValues需要插入的值,插入成功返回一个Uri;
delete():Uri表示需要操作哪张表,selection和selectionArgs表示筛选的条件,返回受影响的行。
update():Uri表示需要操作哪张表,ContentValues需要插入的值,selection和selectionArgs表示筛选的条件,返回受影响的行。
query():Uri表示需要操作哪张表,projection需要查询表中那些字段,selection和selectionArgs表示筛选的条件,sortOrder对查询查询结果进行排序,将查询结果放到Cursor返回。
public class PersonProvider extends ContentProvider {
private static String TAG = PersonProvider.class.getSimpleName();
//这里的AUTHORITY就是我们在AndroidManifest.xml中配置的authorities
public static final String AUTHORITY = "com.dream.contentprovider";
//常量UriMatcher.NO_MATCH表示不匹配任何路径的返回码,也就是说如果找不到匹配的类型,返回-1
private static final UriMatcher URI_MATCHER;
//匹配不同的表的code
private static final int ALL_PERSON = 1;
private static final int PERSON = 2;
//数据库的名字
public static final String DB_NAME = "test.db";
//数据库版本
public static final int DB_VERSION = 1;
//数据库表的名称
private static final String TABLE_NAME = "person";
private MyDBHelper dbHelper;
private SQLiteDatabase db;
static {
//创建一个路径识别器
URI_MATCHER = new UriMatcher(UriMatcher.NO_MATCH);
//1.指定一个路径的匹配规则
//如果路径满足content://com.dream.contentprovider.provider.PersonProvider/person,返回值就是(ALL_PERSON)=1
URI_MATCHER.addURI(AUTHORITY, "/person", ALL_PERSON);
//2.#号为通配符
//如果路径满足content://com.dream.contentprovider.provider.PersonProvider/person/3,返回值就是(PERSON)=2
URI_MATCHER.addURI(AUTHORITY, "/person/#", PERSON);
}
/**
* 一般是对象第一次被创建时调用的方法
*
* @return
*/
@Override
public boolean onCreate() {
dbHelper = new MyDBHelper(this.getContext(), DB_NAME, null, DB_VERSION);
db = dbHelper.getReadableDatabase();
return true;
}
/**
* 让别人去调用返回结果
*
* @param uri 匹配条件
* @param projection 选择的列
* @param selection 查询条件
* @param selectionArgs 查询条件的value
* @param sortOrder 排序
* @return
*/
@Nullable
@Override
public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder) {
int type = URI_MATCHER.match(uri);
switch (type) {
case ALL_PERSON:
return db.query(TABLE_NAME, projection, selection, selectionArgs, null, null, sortOrder);
case PERSON:
//获取具体某一行的数据
String id = uri.getPathSegments().get(1);
return db.query(TABLE_NAME, projection, "_id = ?", new String[]{id}, null, null, sortOrder);
default:
break;
}
return null;
}
//如果是单条记录应该返回以vnd.android.cursor.item/ 为首的字符串
//如果是多条记录,应该返回vnd.android.cursor.dir/ 为首的字符串
@Nullable
@Override
public String getType(@NonNull Uri uri) {
int type = URI_MATCHER.match(uri);
switch (type) {
case ALL_PERSON:
return "vnd.android.cursor.dir/vnd.com.dream.contentprovider.provider.person";
case PERSON:
return "vnd.android.cursor.item/vnd.com.dream.contentprovider.provider.person";
default:
return null;
}
}
@Nullable
@Override
public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {
int type = URI_MATCHER.match(uri);
switch (type) {
case ALL_PERSON:
long row = db.insert(TABLE_NAME, null, values);
return ContentUris.withAppendedId(uri, row);
case PERSON:
long row2 = db.insert(TABLE_NAME, null, values);
return ContentUris.withAppendedId(uri, row2);
default:
return null;
}
}
@Override
public int delete(@NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) {
int type = URI_MATCHER.match(uri);
int updateRow = 0;
switch (type) {
case ALL_PERSON:
updateRow = db.delete(TABLE_NAME, selection, selectionArgs);
break;
case PERSON:
//获取具体某一行的数据
String id = uri.getPathSegments().get(1);
updateRow = db.delete(TABLE_NAME, "_id = ?", new String[]{id});
break;
default:
break;
}
return updateRow;
}
@Override
public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection, @Nullable String[] selectionArgs) {
int type = URI_MATCHER.match(uri);
int updateRow = 0;
switch (type) {
case ALL_PERSON:
updateRow = db.update(TABLE_NAME, values, selection, selectionArgs);
break;
case PERSON:
//获取具体某一行的数据
String id = uri.getPathSegments().get(1);
updateRow = db.update(TABLE_NAME, values, "_id = ?", new String[]{id});
break;
default:
break;
}
return updateRow;
}
}
当APP启动的时候,onCreate()方法被执行,此时已经创建了数据库。
跨进程调用
private static final Uri STUDENT_ALL_URI = Uri.parse("content://" + PersonProvider.AUTHORITY + "/person");拼接完整的地址为:"content://com.dream.contentprovider/person"和"content://com.dream.contentprovider/person/id",其中这个id表示表中数据的行数,id=0、1、 2 ...。当和UriMatcher 进行匹配返回匹配类型。不管是进程内还是跨进程之间通信关键是否URL正确,否则会出现如下错误:
private static final Uri STUDENT_ALL_URI = Uri.parse("content://com.dream.contentprovider/person");
插入数据insert()
mUserProvider = getContentResolver();
ContentValues values = new ContentValues();
values.put("name", "张三");
values.put("age", "18");
values.put("sex", "男");
mUserProvider.insert(STUDENT_ALL_URI, values);
插入数据delete()
mUserProvider = getContentResolver();
mUserProvider.delete(STUDENT_ALL_URI, "name = ?", new String[]{"张三"});
更新数据update()
mUserProvider = getContentResolver();
ContentValues values = new ContentValues();
values.put("age", "19");
values.put("sex", "女");
mUserProvider.update(STUDENT_ALL_URI, values, "name = ?", new String[]{"张三"});
查询数据query()
记得关闭游标,防止内存泄漏
mUserProvider = getContentResolver();
String result = "";
Cursor cursor = mUserProvider.query(STUDENT_ALL_URI, null, null, null);
if (cursor != null) {
try {
while (cursor.moveToNext()) {
String id = cursor.getString(cursor.getColumnIndex("_id"));
String name = cursor.getString(cursor.getColumnIndex("NAME"));
String age = cursor.getString(cursor.getColumnIndex("AGE"));
String sex = cursor.getString(cursor.getColumnIndex("SEX"));
result = result + "\n" + "_id=" + id + " name=" + name + " sex=" + sex + " age=" + age;
}
} finally {
cursor.close();
cursor = null;
mTextView.setText(result);
}
}