7

我已经实施update()ContentProvider通知观察者使用getContext().getContentResolver().notifyChange(uri, null);

我明显的需要是,每当只影响一行时,我想用行特定的 uri 通知,但找不到这样做的方法。像这样的附加查询"select id where selectionArgs"可以做到这一点,但这将是一种愚蠢的方式。

onchange(boolean, uri)获取完整的uri而不是特定的行,很容易理解这是因为ContentProvider.update()发送相同。

some code for more clarity

MyContentProvider 的 update() 方法

 @Override
    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {

        Log.d("TAG", "update " + uri.getPath());

        int count = 0;
        switch (uriMatcher.match(uri)) {
        case BOOKS:
            count = booksDB.update(DATABASE_TABLE, values, selection, selectionArgs);
            break;
        case BOOK_ID:
            count = booksDB.update(DATABASE_TABLE, values,
                    _ID + " = " + uri.getPathSegments().get(1)
                            + (!TextUtils.isEmpty(selection) ? " AND (" + selection + ')' : ""),
                    selectionArgs);
            break;
        default:
            throw new IllegalArgumentException("Unknown URI " + uri);
        }

        if (count == 1) {
            Cursor c = query(uri, new String[] { _ID }, selection, selectionArgs, null);
            long rowId = Long.valueOf(c.getString(c.getColumnIndex(_ID)));
            uri = ContentUris.withAppendedId(CONTENT_URI, rowId);
        }
        getContext().getContentResolver().notifyChange(uri, null);
        return count;

    }

我会更新一些表格

getContentResolver().update(MyContentProvider.CONTENT_URI, values1, MyContentProvider._ID+"<?", new String[]{"3"}));

坦率地说,代码与问题几乎没有关系,只是想给你一些上下文

4

3 回答 3

8

在您的提供者方法中,只需返回附加了 id 的 uri

@Override
public Uri insert(Uri uri, ContentValues values) {
    Log.i(TAG, "insert " + uri);
    final SQLiteDatabase db = mOpenHelper.getWritableDatabase();
    final int match = URI_MATCHER.match(uri);

    Uri returnUri;
    switch (match) {
        case MESSAGE: {
            long _id = db.insert(MessageContract.MessageEntry.TABLE_NAME, null, values);
            if (_id > 0)
                returnUri = ContentUris.withAppendedId(MessageContract.MessageEntry.CONTENT_URI, _id);
            else
                throw new android.database.SQLException("Failed to insert row into " + uri);
            break;
        }

        default:
            throw new UnsupportedOperationException("Unknown uri: " + uri);
    }

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


    return returnUri;
}

并为后代注册你的观察者。

getContentResolver().registerContentObserver(MessageContract.MessageEntry.CONTENT_URI, true, mContentObserver);

要从 Uri 获取 id,您可以使用ContentUris.parseId(uri)

于 2014-10-23T18:31:51.907 回答
1

不幸的是,我无法建议简单的解决方案(因为我不知道您需要运行的完整代码和更新),我们可以尝试一些方法(其中一些我已经在我的应用程序中实现了):

  • 提供 ids ContentValues- 这种方式看起来不适用于您的案例,它需要循环调用notifyChange();
  • 为请求提供特定Uri的查询(只有某些特定的应用程序需要选择多种查询,通常在 中包含查询参数要容易得多Uri)。在程序的另一部分收到特定通知后,Uri它将能够检查它的“当前项目”是否已更新并采取适当的行动(例如,最简单的情况是文章列表和一篇文章在单独的活动中打开;然后您更新文章列表在服务器后台您可能还需要更新当前打开的文章,因此需要知道它是否已更新)。您应该能够使用 just received 来检查观察者一侧的特定项目Uri,因为它(Uri)将包含您用于查询的参数;
于 2013-03-27T06:47:53.843 回答
0

您可以通过 ContentValues 传递 ID,并将其附加到通知 url。这样您就不必进行单独的查询。

@Override
public int update(@NonNull Uri uri, ContentValues values, String selection, String[] selectionArgs) {
    int rows = _database.update(getTableName(), values, selection, selectionArgs);
    if (rows > 0) {
        Uri itemUri = ContentUris.withAppendedId(uri, values.getAsLong(DatabaseModel.COLUMN_ID)); // DatabaseModel.COLUMN_ID is "_id"

        getContext().getContentResolver().notifyChange(itemUri, null);
    }
    return rows;
}
于 2018-03-28T00:01:55.140 回答