Content providers are one of the primary building blocks of Android applications, providing content to applications. They encapsulate data and provide it to applications through the single ContentResolver interface. A content provider is only required if you need to share data between multiple applications. If you don't need to share data amongst multiple applications you can use a database directly via SQLiteDatabase.

照我的理解的话,你可以把ContentProvider 当成是一个适配器。 也就是让应用程序能够通过Content provider提供的接口,调用database 提供的接口来访问database中的数据。也就是说用户可以直接使用ContentResolver操作ContentProvider 来间接访问其它应用程序存在database 中的数据。

下面的例子是实现了这个过程。

一 实现custom content provider

public class ReadingProvider extends ContentProvider {

public static final String AUTHORITY = ReadingProvider.class.getName().toLowerCase();

//下面是定义了两个访问类型的常量。
//访问整张数据表
private static final int TYPE_ALL_ITEMS = 1;
//访问该张表中特定的row的数据
private static final int TYPE_SINGLE_ITEM = 2;

//这个contentprovider对应的数据库
private ReadingOpenHelper dbhelper = null;

//用来匹配content provider的 Uri
private static final UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);

static {
matcher.addURI(AUTHORITY, "items", TYPE_ALL_ITEMS);
//注意这个# 的意思是占位符,对应的uri可以是这样的形式
//static final Uri URI = Uri.parse("content://" + ReadingProvider.AUTHORITY + "/items");
//itemUri = Uri.withAppendedPath(URI, "" + item_id);
matcher.addURI(AUTHORITY, "items/#", TYPE_SINGLE_ITEM);
}

//在这个content provider创建的时候打开数据库
@Override
public boolean onCreate() {
log.debug("readingprovider oncreate");
dbhelper = new ReadingOpenHelper(getContext());
return true;
}

@Override
public int delete(Uri uri, String where, String[] whereArgs){
switch (matcher.match(uri)) {
case TYPE_ALL_ITEMS:

//当匹配TYPE_ALL_ITEMS 这个Uri的时候就删掉ItemColumns.TABLE_NAME 这个table中相应的数据
return dbhelper.getWritableDatabase().delete(ItemColumns.TABLE_NAME, where, whereArgs);
case TYPE_SINGLE_ITEM:

//当匹配TYPE_SINGLE_ITEM 这个Uri的时候就删掉ItemColumns.TABLE_NAME 这个table中用id指定的row的数据
String i_id = uri.getPathSegments().get(1);
return dbhelper.getWritableDatabase().delete(ItemColumns.TABLE_NAME, ItemColumns._ID + "=" + i_id, null);
}
throw new IllegalArgumentException("Unsupported URI: " + uri);
}

@Override
public String getType(Uri uri) {
switch (matcher.match(uri)) {
case TYPE_ALL_ITEMS:
return null;//there is no type so return null
case TYPE_SINGLE_ITEM:
return null;
}
throw new IllegalArgumentException("Unsupported URI: " + uri);
}

@Override
public Uri insert(Uri uri, ContentValues initialValues) {
long id = 0L;
switch (matcher.match(uri)) {
case TYPE_ALL_ITEMS:

//当匹配这个Uri的时候就在(ItemColumns.TABLE_NAME这个table中插入initialValues
id = dbhelper.getWritableDatabase().insertOrThrow(ItemColumns.TABLE_NAME, null, initialValues);
return ContentUris.withAppendedId(ItemColumns.URI, id);
}
throw new IllegalArgumentException("Illegal Uri: " + uri.toString());
}

@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sort) {
//log.debug("reading provider query" + uri.toString());
Cursor cursor = null;
switch (matcher.match(uri)) {
case TYPE_ALL_ITEMS:
cursor = dbhelper.getReadableDatabase().query(ItemColumns.TABLE_NAME, projection, selection, selectionArgs, null, null, sort);
break;
case TYPE_SINGLE_ITEM:
String i_id = uri.getPathSegments().get(1);
cursor = dbhelper.getReadableDatabase().query(ItemColumns.TABLE_NAME, projection, ItemColumns._ID + "=" + i_id, null, null, null, null);
break;
default:
throw new IllegalArgumentException("Illegal Uri: " + uri.toString());
}

if (cursor != null) {
cursor.setNotificationUri(getContext().getContentResolver(), uri);
} else {
log.warn("query failed in reading provider");
}
return cursor;
}

@Override
public int update(Uri uri, ContentValues initialValues, String where, String[] whereArgs) {
switch (matcher.match(uri)) {
case TYPE_ALL_ITEMS:
return dbhelper.getWritableDatabase().update(ItemColumns.TABLE_NAME, initialValues, where, whereArgs);
}
throw new IllegalArgumentException("Illegal Uri: " + uri.toString());
}
}

note: 由上面的content provider的实现我们可以看到,content provider的内部都是在对其相关联的那个数据库进行操作。

二 下面实现这个数据库。 ReadingOpenHelper 继承 SQLiteOpenHelper,使用父类提供的接口来对自己定义的数据库进行相关的操作

1.

public class ReadingOpenHelper extends SQLiteOpenHelper {

private final Log log = Utils.getLog(getClass());

public ReadingOpenHelper(Context context) {
super(context, "bereader.db", null, 1);
}

@Override
public void onCreate(SQLiteDatabase db) {

//下面是创建一个数据库的sql语句
String sql_create_item = cat(
"CREATE TABLE IF NOT EXISTS ", ItemColumns.TABLE_NAME, " (",
ItemColumns._ID, " INTEGER PRIMARY KEY AUTOINCREMENT, ",
ItemColumns.TITLE, " VARCHAR(256)"
");"
);
String sql_index_item_title = cat(
"CREATE UNIQUE INDEX IDX_",
ItemColumns.TABLE_NAME,
"_",
ItemColumns.TITLE,
" ON ",
ItemColumns.TABLE_NAME,
" (",
ItemColumns.TITLE,
");"
);

//执行这个sql语句

db.execSQL(sql_create_item);
db.execSQL(sql_index_item_title);
}

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
log.debug("onUpdate, from: " + oldVersion + " to " + newVersion);
if (oldVersion!=newVersion) {
// drop db 更新数据库的时候要先删掉以前的数据库,这里我们调用onCreate(db);
//来重新生成一个数据库
db.execSQL(cat("DROP TABLE ", ItemColumns.TABLE_NAME));
onCreate(db);
}
}

String cat(String... ss) {
StringBuilder sb = new StringBuilder(ss.length << 3);
for (String s : ss)
sb.append(s);
return sb.toString();
}
}

2.下面这个类就是表示数据库中的一个一个item实体,定义了这个item所在的数据表的名字,用来访问这个数据表的Uri,和这个item的field 这里只有一个TITLE

public interface ItemColumns extends BaseColumns {

//用这个Uri就能够从provider中访问数据库中存储的ItemColumns 的内容

static final Uri URI = Uri.parse("content://" + ReadingProvider.AUTHORITY + "/items");

static final String TABLE_NAME = "beReaderItems";
static final String TITLE = "title";
}

三: 下面我们来使用content provider来访问数据库中的数据。

void testProvider(){

ContentValues cv = new ContentValues();
ContentResolver cr = getContentResolver();

cv.put(ItemColumns.TABLE_NAME, "title_name1");
//插入一条item

cr.insert(ItemColumns.URI,cv);
//查询指定的item

String itemUri = Uri.withAppendedPath(ItemColumns.URI, "" + item_id);
Cursor cursor = cr.query(itemUri,
new String [] {ItemColumns._ID,ItemColumns.TITLE,},
null, null, null);

//更新一条记录

cv.put(ItemColumns.TABLE_NAME, "title_name1");
int n = cr.update(
ItemColumns.URI,
cv,
ItemColumns.URI._ID + "=" + itemId,
null
);
}

更多相关文章

  1. Android(安卓)SQLITE 操作工具类
  2. Android(安卓)使用MediaPlayer播放音乐
  3. android RecycleView实现下拉刷新和上拉加载
  4. ContentProvider-获取系统数据
  5. Android——动态广播、静态广播
  6. Android(安卓)基本原理&移动终端软件开发课程&StudyAccount8 201
  7. android listiew适配器
  8. android不同Activity之间的数据共享
  9. android json 转换

随机推荐

  1. android:屏幕自适应
  2. shape等特殊xml
  3. 电商直播系统开发Android10.0 导航栏和状
  4. Android储存BMP格式图片
  5. Android(安卓)Listview 隐藏滚动条
  6. Android(安卓)postTranslate和preTransla
  7. Android中创建文件夹和文件的操作
  8. 2011.09.26(5)——— android sample之Note
  9. android 抓包
  10. Android之Input子系统事件分发流程