一,写在前面
我们知道Android有四大组件,ContentProvider是其中之一,顾名思义:内容提供者。什么是内容提供者呢?一个抽象类,可以暴露应用的数据给其他应用。应用里的数据通常说的是数据库,事实上普通的文件,甚至是内存中的对象,也可以作为内容提供者暴露的数据形式。为什么要使用内容提供者呢?从上面定义就知道,内容提供者可以实现应用间的数据访问,一般是暴露表格形式的数据库中的数据。内容提供者的实现机制是什么呢?由于是实现应用间的数据通信,自然也是两个进程间的通信,其内部实现机制是Binder机制。那么,内容提供者也是实现进程间通信的一种方式。
事实上在开发中,很少需要自己写一个ContentProvider,一般都是去访问其他应用的ContentProvider。本篇文章之所以去研究如何自己写一个ContentProvider,也是为了更好的在开发中理解:如何访问其他应用的内容提供者。
二,实现一个ContentProvider
接下来介绍如何自己去实现一个内容提供者,大致分三步进行:
1,继承抽象类ContentProvider,重写onCreate,CUDR,getType六个方法;
2,注册可以访问内容提供者的uri
3,清单文件中配置provider
第一步,onCreate()方法中,获取SQLiteDatabase对象;CUDR方法通过对uri进行判断,做相应的增删改查数据的操作;getType方法是返回uri对应的MIME类型。
第二步,创建静态代码块,static{...code},在类加载的时候注册可以访问内容提供者的uri,使用类UriMatcher的addURI(...)完成。
第三步,注册内容提供者,加入authorities属性,对外暴露该应用的内容提供者。
直接上代码,应用B的MyContentProvider,如下:
public class MyContentProvider extends ContentProvider {
private DbOpenHelper helper;
private SQLiteDatabase db;
private static UriMatcher uriMatcher;
public static final String AUTHORITY = "com.example.mycontentprovider.wang";
public static final int CODE_PERSON = 0;
static {
uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
uriMatcher.addURI(AUTHORITY, "person", CODE_PERSON);
}
@Override
public boolean onCreate() {
helper = DbOpenHelper.getInstance(getContext());
db = helper.getWritableDatabase();
//在数据库里添加一些数据
initData();
return true;
}
public void initData() {
for (int i = 0; i < 5; i++) {
ContentValues values = new ContentValues();
values.put("name", "kobe" + (i + 1));
values.put("age", 21 + i);
db.insert("person", null, values);
}
}
@Override
public String getType(Uri uri) {
return null;
}
public String getTableName(Uri uri) {
if (uriMatcher.match(uri) == CODE_PERSON) {
return "person";
} else {
//...
}
return null;
}
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
String tableName = getTableName(uri);
if (tableName == null) {
throw new IllegalArgumentException("uri has not been added by urimatcher");
}
Cursor cursor = db.query(tableName, projection, selection, selectionArgs, null, null, null);
return cursor;
}
@Override
public Uri insert(Uri uri, ContentValues values) {
String tableName = getTableName(uri);
if (tableName == null) {
throw new IllegalArgumentException("uri has not been added by urimatcher");
}
db.insert(tableName, null, values);
//数据库中数据发生改变时,调用
getContext().getContentResolver().notifyChange(uri, null);
return uri;
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
String tableName =