I have an Android ContentProvider
which allows to do LEFT OUTER JOIN
queries on a SQLite database.
我有一个Android ContentProvider,允许在SQLite数据库上执行LEFT OUTER JOIN查询。
Let's assume in the database I have 3 tables, Users
, Articles
and Comments
. The ContentProvider
is something like the following:
让我们假设在数据库中我有3个表,用户,文章和评论。 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?
}
}
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?
每次在Users表中插入(或更新)行时,通知所有监听已加入和未加入查询的CursorAdapter的最佳URI方案是什么?
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.
换句话说,如果我在其中一个表中添加或更新新行,我想用getContext()。getContentResolver()。notifyChange(itemUri,null)发送一个通知,以便所有CursorAdapters监听任何查询( USERS_TABLE,ARTICLES_USERS_JOIN_TABLE,COMMENTS_USERS_JOIN_TABLE)会收到更新其内容的通知。
If this is not possible, is there an alternative way to notify all the observers?
如果这是不可能的,是否有另一种方式通知所有观察者?
2 个解决方案
#1
5
You can have special Uri's to query with:
您可以使用特殊的Uri来查询:
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.
但我想不出发送单一通知的方法。看来你最好的选择是为每个引用被修改表的Uri发送通知。因此,您的插入/更新/删除方法会多次调用notifyChange,具体取决于受影响的表。对于“用户”的更改,它将是3个通知 - 用户,文章用户和评论用户 - 因为它们都依赖于“用户”表。
#2
1
As answered by prodaea, here is another alternative you can use for notification Uri. This is not a perfect solution, but it uses only one Uri for notification.
正如prodaea所回答的,这是另一种可以用于通知Uri的替代方案。这不是一个完美的解决方案,但它只使用一个Uri进行通知。
The solution is to use the main Uri without any table name (e.g:content://com.example.app.provider/) as the notification Uri in the query method for ARTICLES_USERS_JOIN_TABLE
and COMMENTS_USERS_JOIN_TABLE
. So, the related cursor will be notified whenever there is change in any table. There is one limitation though. That is, ARTICLES_USERS_JOIN_TABLE
cursor will be notified even when there is change in Articles
table.
解决方案是使用主要的Uri而不使用任何表名(例如:content://com.example.app.provider/)作为ARTICLES_USERS_JOIN_TABLE和COMMENTS_USERS_JOIN_TABLE的查询方法中的通知Uri。因此,只要任何表发生更改,就会通知相关游标。但有一个限制。也就是说,即使Article表中有变化,也会通知ARTICLES_USERS_JOIN_TABLE游标。
For tables, Users' and
Articles', you can use their specific Uris for notification.
对于表格“用户”和“文章”,您可以使用其特定的Uris进行通知。
#1
5
You can have special Uri's to query with:
您可以使用特殊的Uri来查询:
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.
但我想不出发送单一通知的方法。看来你最好的选择是为每个引用被修改表的Uri发送通知。因此,您的插入/更新/删除方法会多次调用notifyChange,具体取决于受影响的表。对于“用户”的更改,它将是3个通知 - 用户,文章用户和评论用户 - 因为它们都依赖于“用户”表。
#2
1
As answered by prodaea, here is another alternative you can use for notification Uri. This is not a perfect solution, but it uses only one Uri for notification.
正如prodaea所回答的,这是另一种可以用于通知Uri的替代方案。这不是一个完美的解决方案,但它只使用一个Uri进行通知。
The solution is to use the main Uri without any table name (e.g:content://com.example.app.provider/) as the notification Uri in the query method for ARTICLES_USERS_JOIN_TABLE
and COMMENTS_USERS_JOIN_TABLE
. So, the related cursor will be notified whenever there is change in any table. There is one limitation though. That is, ARTICLES_USERS_JOIN_TABLE
cursor will be notified even when there is change in Articles
table.
解决方案是使用主要的Uri而不使用任何表名(例如:content://com.example.app.provider/)作为ARTICLES_USERS_JOIN_TABLE和COMMENTS_USERS_JOIN_TABLE的查询方法中的通知Uri。因此,只要任何表发生更改,就会通知相关游标。但有一个限制。也就是说,即使Article表中有变化,也会通知ARTICLES_USERS_JOIN_TABLE游标。
For tables, Users' and
Articles', you can use their specific Uris for notification.
对于表格“用户”和“文章”,您可以使用其特定的Uris进行通知。