【问题标题】:Android ContentProvider URI scheme to notify CursorAdapters listening on OUTER JOIN queriesAndroid ContentProvider URI 方案以通知 CursorAdapters 侦听 OUTER JOIN 查询
【发布时间】:2012-05-01 20:23:15
【问题描述】:

我有一个 Android ContentProvider,它允许对 SQLite 数据库执行 LEFT OUTER JOIN 查询。

假设在数据库中我有 3 个表,UsersArticlesCommentsContentProvider 类似于以下内容:

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?
    }
}

每次我在Users 表中插入(或更新)一行时,通知所有CursorAdapters 监听连接和非连接查询的最佳URI 方案是什么?

换句话说,如果我在其中一个表中添加或更新新行,我想用getContext().getContentResolver().notifyChange(itemUri, null) 发送一个single 通知,以便所有CursorAdapters 监听任何查询(USERS_TABLEARTICLES_USERS_JOIN_TABLECOMMENTS_USERS_JOIN_TABLE)收到更新其内容的通知。

如果无法做到这一点,是否有其他方法可以通知所有观察者?

【问题讨论】:

    标签: android sqlite join android-contentprovider android-cursor


    【解决方案1】:

    您可以使用特殊的 Uri 进行查询:

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

    但我想不出一种发送单个通知的方法。似乎您最好的选择是为每个引用正在修改的表的 Uri 发送通知。因此,您的插入/更新/删除方法将根据受影响的表多次调用 notifyChange。对于“users”的更改,它将是 3 个通知——users、articlesusers 和 cmetsusers——因为它们都依赖于“users”表。

    【讨论】:

      【解决方案2】:

      正如prodaea 所回答的那样,这是另一种可用于通知 Uri 的替代方案。这不是一个完美的解决方案,但它只使用一个 Uri 进行通知。

      解决方法是在ARTICLES_USERS_JOIN_TABLECOMMENTS_USERS_JOIN_TABLE的查询方法中使用不带任何表名的主Uri(例如:content://com.example.app.provider/)作为通知Uri。因此,只要任何表发生更改,都会通知相关游标。不过有一个限制。即ARTICLES_USERS_JOIN_TABLE游标即使Articles表有变化也会得到通知。

      对于表格,Users' andArticles',您可以使用其特定的 Uris 进行通知。

      【讨论】:

      • 比在 satur9nine's answer! 中建议的每次插入/更新/删除后调用 notifyChange 更优雅!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-01-10
      • 1970-01-01
      • 2014-02-05
      • 1970-01-01
      • 2014-01-15
      • 1970-01-01
      • 2013-03-14
      相关资源
      最近更新 更多