Android ContentProvider URI scheme to notify CursorAdapters listening on OUTER JOIN queries

android, android-contentprovider, android-cursor, join, sqlite

Solution

You can have special Uri's to query with:

    sUriMatcher.addURI(AUTHORITY, "articlesusers", ARTICLES_USERS_JOIN_TABLE);
    sUriMatcher.addURI(AUTHORITY, "commentsusers", COMMENTS_USERS_JOIN_TABLE);

But I can't think of a way to send a single notification. It seems your best choice is to send a notification for each Uri that refers to the table being modified. So your insert/update/delete methods would call notifyChange multiple times depending on the table affected. For changes to "users" it would be 3 notifications--users, articlesusers and commentsusers--since they all depend on the "users" table.

Problem

I have an Android `ContentProvider` which allows to do `LEFT OUTER JOIN` queries on a SQLite database. Let's assume in the database I have 3 tables, `Users`, `Articles` and `Comments`. The `ContentProvider` is something like the following: ``` public class SampleContentProvider extends ContentProvider { private static final UriMatcher sUriMatcher; public static final String AUTHORITY = "com.sample.contentprovider"; private static final int USERS_TABLE = 1; private static final int USERS_TABLE_ID = 2; private static final int ARTICLES_TABLE = 3; private static final int ARTICLES_TABLE_ID = 4; private static final int COMMENTS_TABLE = 5; private static final int COMMENTS_TABLE_ID = 6; private static final int ARTICLES_USERS_JOIN_TABLE = 7; private static final int COMMENTS_USERS_JOIN_TABLE = 8; // [...] other ContentProvider methods @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { String table = getTableName(uri); // SQLiteWrapper is a wrapper class to manage a SQLiteHelper Cursor c = SQLiteWrapper.get(getContext()).getHelper().getReadableDatabase() .query(table, projection, selection, selectionArgs, null, null, sortOrder); c.setNotificationUri(getContext().getContentResolver(), uri); return c; } @Override public Uri insert(Uri uri, ContentValues values) { String table = getTableName(uri); // SQLiteWrapper is a wrapper class to manage a SQLiteHelper long id = SQLiteWrapper.get(getContext()).getHelper().getWritableDatabase() .insert(table, null, values); Uri itemUri = ContentUris.withAppendedId(uri, id); getContext().getContentResolver().notifyChange(itemUri, null); return itemUri; } private String getTableName(Uri uri) { switch (sUriMatcher.match(uri)) { case USERS_TABLE: case USERS_TABLE_ID: return "Users"; case ARTICLES_TABLE: case ARTICLES_TABLE_ID: return "Articles"; case COMMENTS_TABLE: case COMMENTS_TABLE_ID: return "Comments"; case ARTICLES_USERS_JOIN_TABLE: return "Articles a LEFT OUTER JOIN Users u ON (u._id = a.user_id)"; case COMMENTS_USERS_JOIN_TABLE: return "Comments c LEFT OUTER JOIN Users u ON (u._id = c.user_id)"; default: throw new IllegalArgumentException("Unknown URI " + uri); } } static { sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH); sUriMatcher.addURI(AUTHORITY, "users", USERS_TABLE); sUriMatcher.addURI(AUTHORITY, "articles", ARTICLES_TABLE); sUriMatcher.addURI(AUTHORITY, "comments", COMMENTS_TABLE); sUriMatcher.addURI(AUTHORITY, "users" + "/#", USERS_TABLE_ID); sUriMatcher.addURI(AUTHORITY, "articles" + "/#", ARTICLES_TABLE_ID); sUriMatcher.addURI(AUTHORITY, "comments" + "/#", COMMENTS_TABLE_ID); sUriMatcher.addURI(AUTHORITY, "???", ARTICLES_USERS_JOIN_TABLE); // what uri here? sUriMatcher.addURI(AUTHORITY, "???", COMMENTS_USERS_JOIN_TABLE); // what uri here? } } ``` What's the best URI scheme to notify all `CursorAdapter`s listening on joined and non-joined queries every time I insert (or update) a row in the `Users` table? In other words, if I add or update a new row in one of the tables, I want to send a single notification with `getContext().getContentResolver().notifyChange(itemUri, null)` so that all the `CursorAdapter`s listening on any query (`USERS_TABLE`, `ARTICLES_USERS_JOIN_TABLE`, `COMMENTS_USERS_JOIN_TABLE`) receive a notification to update their content. If this is not possible, is there an alternative way to notify all the observers?

Original source

Related problems