【问题标题】:CursorLoader notify data changeCursorLoader 通知数据变化
【发布时间】:2014-10-16 22:00:52
【问题描述】:

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

主要的:

//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));
}

最后MyContentProvider 中的insert 方法是这样定义的:

@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,我可以看到插入的数据,所以它只是通知不起作用。我应该更改哪些内容才能正确通知加载程序?

【问题讨论】:

  • 如果您完全删除 setNotificationUri() 行,您会收到更新吗?
  • 另外,您选择使用不同的 URI 与使用 where 语句进行过滤是否有特殊原因?
  • @ianhanniballake 1- 如果我完全删除 setNotificationUri,我看不到任何变化。我只看到预先存在的数据。 2-我使用了两个不同的URI,因为我还在学习,刚刚我意识到cursorloader构造函数有selection和selectionArgs参数。我会尽量简化代码
  • 你能测试一件事吗:尝试删除 BASEURI 中的最后一个斜杠
  • @Selvin 抱歉,在编辑代码以使其更“通用”时,我添加了一个额外的斜杠,它在我的原始代码中不存在。我也编辑了问题。

标签: java android android-contentprovider android-contentresolver


【解决方案1】:

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

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

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

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

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

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

【讨论】:

  • ContentProvider更简单解决了问题!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多