How to suspend notification to observers while doing many changes using a ContentProvider

喜欢而已 提交于 2019-12-08 08:43:32

问题


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?


回答1:


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.




回答2:


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.



来源:https://stackoverflow.com/questions/4292182/how-to-suspend-notification-to-observers-while-doing-many-changes-using-a-conten

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!