CursorLoader通知数据更改

时间:2014-10-16 12:09:31

标签: java android android-contentprovider android-contentresolver

我已经实现了我的自定义ContentProvider,它有几个URI s:

主要的一个:

//Return all items, uriType = ALLITEMS
String BASEURI = "content://authority/items"

//Return all items in category #, uriType = ITEMS
"content://authority/items/cat/#" 
//Return all items in category # starting with *, uriType = ITEMS_INITIAL
"content://authority/items/cat/#/*"

我的Activity实现了这些Loader回调:

@Override
public Loader<Cursor> onCreateLoader(int id, Bundle arg1) {
    CursorLoader mCursorLoader = null;
    switch (id) {
    case 0:
        mCursorLoader = new CursorLoader(
                mActivity,
                Uri.parse("content://authority/items/cat/"
                        +mCurrentID), mColumns, null, null, null);
        break;
    }
    return mCursorLoader;
}

@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
    switch (loader.getId()) {
    case 0:
        cursor.setNotificationUri(getContentResolver(),MyContentProvider.BASEURI);
        if (null == mAdapter)
            mAdapter = new GridViewCursorAdapter(this, cursor,0);
        //gv is a GridView
        if (gv.getAdapter() != mAdapter)
            gv.setAdapter(mAdapter);
        if (mAdapter.getCursor() != cursor)
            mAdapter.swapCursor(cursor);
        break;
    }
}

@Override
public void onLoaderReset(Loader<Cursor> arg0) {
    mAdapter.swapCursor(null);
}

当我想插入我使用的数据时:

for (ItemClass item : itemsToInsert) {
    getContentResolver().insert(MyContentProvider.BASEURI, itemToContentValues(item));
}

最后insert中的MyContentProvider方法如此定义:

@Override
public Uri insert(Uri uri, ContentValues values) {
    SQLiteDatabase database = db.getWritableDatabase();
    int turiType = sURIMatcher.match(uri);
    long id = 0;
    switch (uriType) {
    case ALLITEMS:
        id = database.insert(MySQLiteHelper.TABLE_ITEMS, null, values);
        break;
    default:
        throw new IllegalArgumentException("Unknown URI (" + uri + ")");
    }
    getContext().getContentResolver().notifyChange(uri, null);
    return null;//I will implement uri path to single item later
}

如您所见,用于初始化Loader的默认URI是按类别ID过滤而不是BASEURI过滤,但我使用Cursor.setNotificationUri将通知URI设置为BASEURI,但我的GridView内容未更新。

如果我重新启动Activity我可以看到插入的数据,所以只是通知不起作用。我应该更改什么才能正确通知装载机?

1 个答案:

答案 0 :(得分:2)

ContentProvider(和任何数据库)中进行过滤的最佳方法是使用where语句。在这种情况下,这意味着您的CursorLoader看起来像:

mCursorLoader = new CursorLoader(
  mActivity,
  MyContentProvider.BASEURI,
  mColumns, 
  MyContentProviderColumns.CATEGORY + "=?", // category = ?
  new String[] { Integer.toString(mCurrentID) }, // pass in your category
  null);

传入选择,过滤您调用的类别列,选择参数args是类别值本身。在这种情况下,您只有一个URI,因此更改通知更容易管理。

如果你真的需要单独的URI,另一个选择就是在notify语句中进行多次insert次调用:

getContext().getContentResolver().notifyChange(uri, null);

int category = extractCategoryFromContentValues(values);
getContext().getContentResolver().notifyChange("content://authority/items/cat/"
                    + category, null);