编写完整的Content provider示例

来源:互联网 发布:英文版超市软件 编辑:程序博客网 时间:2024/05/20 11:49

在在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的使用
  • 在content provider中使用二进制数据

 

 

相关日志

转:http://marshal.easymorse.com/archives/2991