編寫完整的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/

 

 

相關日誌

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

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章