簡體   English   中英

如何在使用ContentProvider進行許多更改時暫停向觀察者的通知

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

我有一個ExpandableListView,它使用SimpleCursorTreeAdapter,后者使用ContentProvider返回的游標。 這很好,因為它始終與數據保持同步,但是有時我需要對數據庫進行許多更改,以便在同一秒內多次重新查詢游標。 是否可以暫停ContentObservers的通知以避免不必要的重新查詢?

一種可能的解決方案是修改內容提供者以允許暫停通知。 將要通知的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;
}

我不確定如何最好地啟用/禁用掛起,但是一種可能是在update()方法中使用一個特殊的URI來打開/關閉掛起(例如content:// <authority> / 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;
    ... 
    }
}

現在,對數據庫進行更改的服務可以在ContentProvider啟動時掛起它,而在完成時禁用掛起。

您可以使用http://developer.android.com/reference/android/widget/BaseAdapter.html#unregisterDataSetObserver(android.database.DataSetObserver )取消注冊偵聽器,一旦工作准備就緒,可以再次注冊它們嗎? 在我看來,這就像一個AsyncTask。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM