notifyChange with changed uri from contentProvider.update()
Asked Answered
S

3

7

i have implemented update() of ContentProvider and notifying to observer using getContext().getContentResolver().notifyChange(uri, null);

my obvious need is that whenever just one row is effected i want to notify with row specific uri, but could not find way to do so. an additional query like "select id where selectionArgs" can do this but this will be a foolish way.

onchange(boolean, uri) get complete uri instead of specific row, easy to understand that this is because ContentProvider.update() is sending the same.

some code for more clarity

update() method of MyContentProvider

 @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;

    }

i will update table some how like

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

frankly saying, code has barely related to question, just trying to give you some context

Snort answered 25/3, 2013 at 8:31 Comment(2)
Some code might be useful. How do You update many rows?Brood
Make sure you call setNotificationUri(ContentResolver cr, Uri uri) on the cursor returned by the query() method of yout content provider. More info at #7915550 .Almsgiver
T
9

In your provider method, just return the uri with the id appended

@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;
}

And register your observer with true for descendents.

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

To get the id from a Uri you can use ContentUris.parseId(uri)

Tabret answered 23/10, 2014 at 18:31 Comment(1)
The original question was for update not insert though. Update returns the number of rows updated, while insert returns the Id. With update you can't use this method.Peirce
B
1

Unfortunately I'm not able to suggest easy solution (because I'm not aware of full code and updates You need to run), there's some ways we You could try (some of them I've implemented in mine applications):

  • Provide ids in ContentValues - this way looks not applicable for Your case and it needs loop with calls to notifyChange();
  • Provide specific Uri for requests with queries (only some specific apps needs many various queries in selection, usually it's much easier to include query parameter in Uri). After another part of the program get notification with that specific Uri it will be able to check if it's 'current item' was updated and act appropriately (e.g. simplest case with list of articles and one article open in separate activity; then You update list of articles in the background from server You might need to update currently open article also and so, need to know if it was updated). You should be able to check particular item on the side of the observer using just received Uri, because it (Uri) will contain parameter(s) You've used for query;
Brood answered 27/3, 2013 at 6:47 Comment(2)
>> You should be able to check particular item on the side of the observer using just received Uri, because it (Uri) will contain parameter(s) <<. i wish its true :( in my case uri is simply what i send in update query and do not involve parameters automatically. i guess one need to do that manually in ContentProvider#update(). and my question is about how to do that .Snort
I meant, You can introduce specific Uri like BASE/updateItemsWith/dateLater/<some value> instead of using BASE/updateItemsWith and providing selection in update arguments. Then in observer You would be able to have BASE/updateItemsWith/dateLater/<some value> and check particular item using it.Brood
P
0

You can pass the ID via ContentValues, and append it to the notification url. This way you don't have to make a separate query.

@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;
}
Peirce answered 28/3, 2018 at 0:1 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.