编写完整的Content provider示例

在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/


allowtransparency="true" frameborder="0" hspace="0" id="I1_1311652872151" marginheight="0" marginwidth="0" name="I1_1311652872151" scrolling="no" src="https://plusone.google.com/u/0/_/+1/fastbutton?url=http%3A%2F%2Fmarshal.easymorse.com%2Farchives%2F2991&size=standard&count=true&db=1&hl=zh-CN&jsh=r%3Bgc%2F22595239-f24a003b#id=I1_1311652872151&parent=http%3A%2F%2Fmarshal.easymorse.com&rpctoken=707305435&_methods=onPlusOne%2C_ready%2C_close%2C_open%2C_resizeMe" tabindex="-1" vspace="0" width="100%" style="position: absolute; left: -10000px; top: -10000px; width: 106px; ">

在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/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值