如何在使用 ContentProvider 进行许多更改时暂停通知观察者

发布于 2024-10-04 12:32:40 字数 172 浏览 9 评论 0原文

我有一个 ExpandableListView,它使用 SimpleCursorTreeAdapter,它使用 ContentProvider 返回的游标。这很好,因为它始终与数据保持同步,但有时我需要对数据库进行许多更改,以便在同一秒内多次重新查询游标。是否可以暂停ContentObservers的通知以避免不必要的重新查询?

I have an ExpandableListView that uses a SimpleCursorTreeAdapter which uses the cursors returned by a ContentProvider. This is fine as it always keeps in sync with the data but sometimes I need to do many changes to the database so that the cursor is requeried many times in the same second. Is it possible to suspend the notification of ContentObservers to avoid unnecessary requerys?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

唔猫 2024-10-11 12:32:40

一种可能的解决方案是修改内容提供程序以允许暂停通知。要通知的 URI 将添加到队列中,直到禁用暂停为止。

private boolean suspendNotifications = false;
private LinkedList<Uri> suspendedNotifications = new LinkedList<Uri>();
private HashSet<Uri> suspendedNotificationsSet = new HashSet<Uri>();

    private void notifyChange(Uri uri) {
    if (suspendNotifications) {
        synchronized (suspendedNotificationsSet) { // Must be thread-safe
            if (suspendedNotificationsSet.contains(uri)) {
                // In case the URI is in the queue already, move it to the end.
                // This could lead to side effects because the order is changed
                // but we also reduce the number of outstanding notifications.
                suspendedNotifications.remove(uri); 
            }
            suspendedNotifications.add(uri);
            suspendedNotificationsSet.add(uri);
        }
    }
    else {
        getContext().getContentResolver().notifyChange(uri, null);
    }
}

private void notifyOutstandingChanges() {
    Uri uri;
    while ((uri = suspendedNotifications.poll()) != null) {
        getContext().getContentResolver().notifyChange(uri, null);
        suspendedNotificationsSet.remove(uri);
    }
}

private void setNotificationsSuspended(boolean suspended) {
    this.suspendNotifications = suspended;
    if (!suspended) notifyOutstandingChanges();
}

@Override
public Uri insert(Uri uri, ContentValues values) {
    ...
    notifyChange(uri);
    return newItemUri;
}

一个特殊的 URI 来打开/关闭暂停(例如 content:///suspension):

@Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
    switch (uriMatcher.match(uri)) {
    ...
    case SUSPEND:
        boolean enabled = values.getAsBoolean("enabled");
        setNotificationsSuspended(enabled);
        break;
    ... 
    }
}

我不确定如何最好地启用/禁用暂停,但一种可能是在 update() 方法中使用 对数据库进行更改的操作现在可以在 ContentProvider 启动时挂起它,并在其完成时禁用挂起。

A possible solution is to modify the content provider to allow suspending notifications. URIs to be notified are added to a queue until suspension is disabled.

private boolean suspendNotifications = false;
private LinkedList<Uri> suspendedNotifications = new LinkedList<Uri>();
private HashSet<Uri> suspendedNotificationsSet = new HashSet<Uri>();

    private void notifyChange(Uri uri) {
    if (suspendNotifications) {
        synchronized (suspendedNotificationsSet) { // Must be thread-safe
            if (suspendedNotificationsSet.contains(uri)) {
                // In case the URI is in the queue already, move it to the end.
                // This could lead to side effects because the order is changed
                // but we also reduce the number of outstanding notifications.
                suspendedNotifications.remove(uri); 
            }
            suspendedNotifications.add(uri);
            suspendedNotificationsSet.add(uri);
        }
    }
    else {
        getContext().getContentResolver().notifyChange(uri, null);
    }
}

private void notifyOutstandingChanges() {
    Uri uri;
    while ((uri = suspendedNotifications.poll()) != null) {
        getContext().getContentResolver().notifyChange(uri, null);
        suspendedNotificationsSet.remove(uri);
    }
}

private void setNotificationsSuspended(boolean suspended) {
    this.suspendNotifications = suspended;
    if (!suspended) notifyOutstandingChanges();
}

@Override
public Uri insert(Uri uri, ContentValues values) {
    ...
    notifyChange(uri);
    return newItemUri;
}

I'm not sure how to best enable/disable suspension but one possibility would be to have a special URI which turns on/off suspension (e.g. content://<authority>/suspension) in the update() method:

@Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
    switch (uriMatcher.match(uri)) {
    ...
    case SUSPEND:
        boolean enabled = values.getAsBoolean("enabled");
        setNotificationsSuspended(enabled);
        break;
    ... 
    }
}

The service that does the changes to the database can now suspend the ContentProvider when it starts and disable suspension when it finishes.

街角迷惘 2024-10-11 12:32:40

您可以使用 http://developer.android. com/reference/android/widget/BaseAdapter.html#unregisterDataSetObserver(android.database.DataSetObserver) 取消注册您的侦听器,并在您的工作准备就绪后再次注册它们,这对我来说听起来像是 AsyncTask 。

Can you use http://developer.android.com/reference/android/widget/BaseAdapter.html#unregisterDataSetObserver(android.database.DataSetObserver) to unRegister your listeners and once your work is ready, register them again? Sounds like a AsyncTask to me.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文