Схема URI Android ContentProvider для уведомления CursorAdapters, прослушивающих запросы OUTER JOIN
У меня есть Android ContentProvider
, который позволяет делать запросы LEFT OUTER JOIN
в базе данных SQLite.
Предположим, что в базе данных есть 3 таблицы, Users
, Articles
и Comments
. ContentProvider
выглядит следующим образом:
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?
}
}
Какая лучшая схема URI уведомляет все CursorAdapter
прослушивание подключенных и несвязанных запросов каждый раз, когда я вставляю (или обновляю) строку в таблице Users
?
Другими словами, если я добавляю или обновляю новую строку в одной из таблиц, я хочу отправить уведомление одиночное с помощью getContext().getContentResolver().notifyChange(itemUri, null)
, чтобы все CursorAdapter
прослушивали любой запрос (USERS_TABLE
, ARTICLES_USERS_JOIN_TABLE
, COMMENTS_USERS_JOIN_TABLE
) получают уведомление об обновлении своего контента.
Если это невозможно, есть ли альтернативный способ оповестить всех наблюдателей?
Ответы
Ответ 1
У вас может быть специальный Uri для запроса:
sUriMatcher.addURI(AUTHORITY, "articlesusers", ARTICLES_USERS_JOIN_TABLE);
sUriMatcher.addURI(AUTHORITY, "commentsusers", COMMENTS_USERS_JOIN_TABLE);
Но я не могу придумать способ отправить одно уведомление. Кажется, ваш лучший выбор - отправить уведомление для каждого Uri, относящегося к изменяемой таблице. Таким образом, ваши методы вставки/обновления/удаления вызовут notifyChange несколько раз в зависимости от затронутой таблицы. Для внесения изменений в "пользователей" было бы 3 уведомления - пользователи, статьи и пользователи комментариев, поскольку все они зависят от таблицы "users".
Ответ 2
Как указано prodaea, вот еще одна альтернатива, которую вы можете использовать для уведомления Uri. Это не идеальное решение, но для уведомления используется только один Uri.
Решение состоит в том, чтобы использовать основной Uri без имени таблицы (например: content://com.example.app.provider/) в качестве уведомления Uri в методе запроса для ARTICLES_USERS_JOIN_TABLE
и COMMENTS_USERS_JOIN_TABLE
. Таким образом, связанный курсор будет уведомлен о каждом изменении таблицы. Однако есть одно ограничение. То есть, ARTICLES_USERS_JOIN_TABLE
курсор будет уведомлен, даже если в таблице Articles
есть изменения.
Для таблиц Users' and
Articles 'вы можете использовать свой специальный Uris для уведомления.