`

编写完整的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/


<iframe 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&amp;size=standard&amp;count=true&amp;db=1&amp;hl=zh-CN&amp;jsh=r%3Bgc%2F22595239-f24a003b#id=I1_1311652872151&amp;parent=http%3A%2F%2Fmarshal.easymorse.com&amp;rpctoken=707305435&amp;_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; "></iframe>

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

分享到:
评论

相关推荐

    Android开发案例驱动教程 配套代码

    11.6.1 编写Content Provider 269 11.6.2 在不同的应用中调用Content Provider 277 11.6.3 重构Content Provider调用 278 本章小结 281 第12章 多媒体 282 12.1 多媒体文件介绍 282 12.1.1 音频多媒体文件介绍...

    dontcamp_bf2:为 DontCamp.com 编写的战地 2 Python 脚本

    dc_ass_extensions.py:dc_ass 的一些基本扩展,提供有用的功能,并作为如何编写自定义扩展的示例。 dc_debug.py:DontCamp.com BF2 Python 脚本的通用调试日志库。 dc_irs.py(DontcCamp.com 游戏内报告系统):一...

    精通ANDROID 3(中文版)1/2

    14.1.2 编写简单的接收程序:示例代码  14.1.3 在描述文件中注册接收程序  14.1.4 发送测试广播  14.1.5 容纳多个接收程序  14.1.6 进程外接收程序项目  14.2 从接收程序使用通知  14.2.1 通过通知管理...

    精通Android 3 (中文版)2/2

    14.1.2 编写简单的接收程序:示例代码  14.1.3 在描述文件中注册接收程序  14.1.4 发送测试广播  14.1.5 容纳多个接收程序  14.1.6 进程外接收程序项目  14.2 从接收程序使用通知  14.2.1 通过通知管理...

    新版Android开发教程.rar

    ----------------------------------- Android 编程基础 1 封面----------------------------------- Android 编程基础 2 开放手机联盟 --Open --Open --Open --Open Handset Handset Handset Handset Alliance ...

    JAVA上百实例源码以及开源项目源代码

    Java日期选择控件完整源代码 14个目标文件 内容索引:JAVA源码,系统相关,日历,日期选择  Java语言开发的简洁实用的日期选择控件,源码文件功能说明:  [DateChooser.java] Java 日期选择控件(主体类) [public]  ...

    JAVA上百实例源码以及开源项目

    Java日期选择控件完整源代码 14个目标文件 内容索引:JAVA源码,系统相关,日历,日期选择  Java语言开发的简洁实用的日期选择控件,源码文件功能说明:  [DateChooser.java] Java 日期选择控件(主体类) [public]  ...

    APKTool批处理版l

    ”@id/ad” android:layout_width=”fill_parent” android:layout_height=”wrap_content” admobsdk:backgroundColor=”#ff000000″ admobsdk:textColor=”#ffffffff” admobsdk:keywords=”Android application”...

Global site tag (gtag.js) - Google Analytics