在在Content provider实现中使用SQLiteOpenHelper中实现的是特别简单的content provider,方法实现不全。下面给出一个实现比较全面的Content provider,当然也是很简单的。
使用UriMatcher
UriMatcher可以帮助开发者识别Uri。比如:
content://com.easymorse.cp.mycp/emperors
表示获取朝代列表集合。而:
content://com.easymorse.cp.mycp/emperors/1
表示其中的_ID值为1的一个特定的记录。
如果自己写分析Uri的代码,比较繁琐和重复。android提供了方便的工具类UriMatcher。
首先定义两个常量,针对集合与特定的单条记录:
private static final int ITEMS = 1;
private static final int ITEM = 2;
另外要创建UriMatcher实例:
private static UriMatcher uriMatcher;
static {
uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
uriMatcher.addURI(PROVIDER_NAME, TABLE_EMPERORS, ITEMS);
uriMatcher.addURI(PROVIDER_NAME, TABLE_EMPERORS + "/#", ITEM);
}
静态即可。然后在静态初始化块中把ITEMS和ITEM加进去。这里指定了ITEMS的URI模式是:
content://com.easymorse.cp.mycp/emperors
而ITEM是:
content://com.easymorse.cp.mycp/emperors/#
#号表示一个id值。
UriMatcher如何使用呢?
uriMatcher.match(uri)
如果一个content://com.easymorse.cp.mycp/emperors Uri,该方法将返回1,也就是常量ITEMS的值,以此类推。
编写一个getType方法:
@Override
public String getType(Uri uri) {
switch (uriMatcher.match(uri)) {
case ITEMS:
return "vnd.android.cursor.dir/vnd.easymorse.mycp";
case ITEM:
return "vnd.android.cursor.item/vnd.easymorse.mycp";
default:
throw new IllegalArgumentException("Unsupported URI: " + uri);
}
}
这个方法在本例中并未起到作用,如果作为intent并使用data(Mimetype)就会用到这个方法。可见总结一下Intent概念的data测试部分。
编写查询方法
查询方法的代码:
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
switch (uriMatcher.match(uri)) {
case ITEMS:
return database.query(TABLE_EMPERORS, projection, selection,
selectionArgs, null, null, sortOrder);
case ITEM:
return database.query(TABLE_EMPERORS, projection, _ID + "="
+ uri.getPathSegments().get(1), selectionArgs, null, null,
null);
default:
throw new IllegalArgumentException("unknown uri: " + uri);
}
}
这里有两种可能,通过条件查询,或者通过id查询,前者走ITEMS,后者走ITEM,都是通过Uri判断的,借助UriMatcher。这里:
uri.getPathSegments().get(1),
将取到id号。如果get(0),将取到path的第一个值emperors。
使用该Content provider的代码:
private String getContentProviderValues() {
StringBuilder builder = new StringBuilder();// 查名称和朝代,朝代=明,而且按照登基时间倒排序
Cursor cursor = managedQuery(MyContentProvider.CONTENT_URI,
new String[] { MyContentProvider.NAME,
MyContentProvider.DYNASTY }, MyContentProvider.DYNASTY
+ "=?", new String[] { "明" }, " start_year desc");// 查全部记录
// Cursor cursor = managedQuery(MyContentProvider.CONTENT_URI, null,
// null,
// null, null);// 根据id定位记录(0..1)
// Cursor cursor = managedQuery(ContentUris.withAppendedId(
// MyContentProvider.CONTENT_URI, 1),
// new String[] { MyContentProvider.NAME }, null, null, null);while (cursor.moveToNext()) {
builder
.append(
cursor.getString(cursor
.getColumnIndex(MyContentProvider.NAME)))
.append(" | ")
// .append(
// cursor
// .getString(cursor
// .getColumnIndex(MyContentProvider.START_YEAR)))
// .append(" | ")
.append(
cursor.getString(cursor
.getColumnIndex(MyContentProvider.DYNASTY)))
.append("\n");
}
可以有多种使用方式,本例中屏蔽部分,是其他使用方式。
编写编辑方法
insert()、update()和delete()都属于编辑记录的功能。拿update举例,因为比较复杂一点:
@Override
public int update(Uri uri, ContentValues contentValues, String selection,
String[] selectionArgs) {
switch (uriMatcher.match(uri)) {
case ITEM:
return database.update(TABLE_EMPERORS, contentValues,
_ID + "=" + uri.getPathSegments().get(1) + " and ("
+ selection + ")", selectionArgs);
case ITEMS:
return database.update(TABLE_EMPERORS, contentValues, selection,
selectionArgs);
default:
throw new IllegalArgumentException("unknown uri: " + uri);
}
}
这里复杂的地方是如果根据id做修改,比如还有其他附加条件,需要拼接where子句字符串。后面的and要带括号,否则逻辑可能不同。
使用这个Content provider的做update的示例:
ContentValues values = new ContentValues();
values.put(MyContentProvider.NAME, "朱重八");
getContentResolver().update(MyContentProvider.CONTENT_URI, values,
MyContentProvider.NAME + "=?", new String[] { "朱元璋" });
修改表中是朱元璋的,改为他的小名,朱重八。
如果是delete和insert操作,情况是类似的。
完整示例见:
http://easymorse.googlecode.com/svn/tags/content.provider-0.3.0/
在在Content provider实现中使用SQLiteOpenHelper中实现的是特别简单的content provider,方法实现不全。下面给出一个实现比较全面的Content provider,当然也是很简单的。
使用UriMatcher
UriMatcher可以帮助开发者识别Uri。比如:
content://com.easymorse.cp.mycp/emperors
表示获取朝代列表集合。而:
content://com.easymorse.cp.mycp/emperors/1
表示其中的_ID值为1的一个特定的记录。
如果自己写分析Uri的代码,比较繁琐和重复。android提供了方便的工具类UriMatcher。
首先定义两个常量,针对集合与特定的单条记录:
private static final int ITEMS = 1;
private static final int ITEM = 2;
另外要创建UriMatcher实例:
private static UriMatcher uriMatcher;
static {
uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
uriMatcher.addURI(PROVIDER_NAME, TABLE_EMPERORS, ITEMS);
uriMatcher.addURI(PROVIDER_NAME, TABLE_EMPERORS + "/#", ITEM);
}
静态即可。然后在静态初始化块中把ITEMS和ITEM加进去。这里指定了ITEMS的URI模式是:
content://com.easymorse.cp.mycp/emperors
而ITEM是:
content://com.easymorse.cp.mycp/emperors/#
#号表示一个id值。
UriMatcher如何使用呢?
uriMatcher.match(uri)
如果一个content://com.easymorse.cp.mycp/emperors Uri,该方法将返回1,也就是常量ITEMS的值,以此类推。
编写一个getType方法:
@Override
public String getType(Uri uri) {
switch (uriMatcher.match(uri)) {
case ITEMS:
return "vnd.android.cursor.dir/vnd.easymorse.mycp";
case ITEM:
return "vnd.android.cursor.item/vnd.easymorse.mycp";
default:
throw new IllegalArgumentException("Unsupported URI: " + uri);
}
}
这个方法在本例中并未起到作用,如果作为intent并使用data(Mimetype)就会用到这个方法。可见总结一下Intent概念的data测试部分。
编写查询方法
查询方法的代码:
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
switch (uriMatcher.match(uri)) {
case ITEMS:
return database.query(TABLE_EMPERORS, projection, selection,
selectionArgs, null, null, sortOrder);
case ITEM:
return database.query(TABLE_EMPERORS, projection, _ID + "="
+ uri.getPathSegments().get(1), selectionArgs, null, null,
null);
default:
throw new IllegalArgumentException("unknown uri: " + uri);
}
}
这里有两种可能,通过条件查询,或者通过id查询,前者走ITEMS,后者走ITEM,都是通过Uri判断的,借助UriMatcher。这里:
uri.getPathSegments().get(1),
将取到id号。如果get(0),将取到path的第一个值emperors。
使用该Content provider的代码:
private String getContentProviderValues() {
StringBuilder builder = new StringBuilder();// 查名称和朝代,朝代=明,而且按照登基时间倒排序
Cursor cursor = managedQuery(MyContentProvider.CONTENT_URI,
new String[] { MyContentProvider.NAME,
MyContentProvider.DYNASTY }, MyContentProvider.DYNASTY
+ "=?", new String[] { "明" }, " start_year desc");// 查全部记录
// Cursor cursor = managedQuery(MyContentProvider.CONTENT_URI, null,
// null,
// null, null);// 根据id定位记录(0..1)
// Cursor cursor = managedQuery(ContentUris.withAppendedId(
// MyContentProvider.CONTENT_URI, 1),
// new String[] { MyContentProvider.NAME }, null, null, null);while (cursor.moveToNext()) {
builder
.append(
cursor.getString(cursor
.getColumnIndex(MyContentProvider.NAME)))
.append(" | ")
// .append(
// cursor
// .getString(cursor
// .getColumnIndex(MyContentProvider.START_YEAR)))
// .append(" | ")
.append(
cursor.getString(cursor
.getColumnIndex(MyContentProvider.DYNASTY)))
.append("\n");
}
可以有多种使用方式,本例中屏蔽部分,是其他使用方式。
编写编辑方法
insert()、update()和delete()都属于编辑记录的功能。拿update举例,因为比较复杂一点:
@Override
public int update(Uri uri, ContentValues contentValues, String selection,
String[] selectionArgs) {
switch (uriMatcher.match(uri)) {
case ITEM:
return database.update(TABLE_EMPERORS, contentValues,
_ID + "=" + uri.getPathSegments().get(1) + " and ("
+ selection + ")", selectionArgs);
case ITEMS:
return database.update(TABLE_EMPERORS, contentValues, selection,
selectionArgs);
default:
throw new IllegalArgumentException("unknown uri: " + uri);
}
}
这里复杂的地方是如果根据id做修改,比如还有其他附加条件,需要拼接where子句字符串。后面的and要带括号,否则逻辑可能不同。
使用这个Content provider的做update的示例:
ContentValues values = new ContentValues();
values.put(MyContentProvider.NAME, "朱重八");
getContentResolver().update(MyContentProvider.CONTENT_URI, values,
MyContentProvider.NAME + "=?", new String[] { "朱元璋" });
修改表中是朱元璋的,改为他的小名,朱重八。
如果是delete和insert操作,情况是类似的。
完整示例见:
http://easymorse.googlecode.com/svn/tags/content.provider-0.3.0/