1

Ich habe eine ExpandableListView, die einen SimpleCursorTreeAdapter verwendet, der die von einem ContentProvider zurückgegebenen Cursor verwendet. Dies ist in Ordnung, da es immer synchron mit den Daten bleibt, aber manchmal muss ich viele Änderungen an der Datenbank vornehmen, so dass der Cursor mehrmals in derselben Sekunde abgefragt wird. Ist es möglich, die Benachrichtigung von ContentObserver zu unterbrechen, um unnötige Anfragen zu vermeiden?So suspendieren Sie Benachrichtigungen an Beobachter, während Sie viele Änderungen mit einem ContentProvider durchführen

Antwort

1

Eine mögliche Lösung besteht darin, den Inhaltsanbieter so zu ändern, dass Benachrichtigungen ausgesetzt werden können. Zu benachrichtigende URIs werden einer Warteschlange hinzugefügt, bis die Aussetzung deaktiviert ist.

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

Ich bin nicht sicher, wie sie am besten aktivieren/deaktivieren Suspension aber eine Möglichkeit, eine spezielle URI zu haben wäre, der sich einschaltet/Aus-Suspension (zB Inhalt: // < Behörde >/Suspension) im Update() -Methode:

@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; 
    ... 
    } 
} 

der Dienst, die Änderungen an der Datenbank tut können nun die Contentprovider aussetzen, wenn es beginnt, und deaktivieren sie Aufhängung, wenn es fertig ist.

0

Können Sie http://developer.android.com/reference/android/widget/BaseAdapter.html#unregisterDataSetObserver(android.database.DataSetObserver) verwenden, um die Registrierung Ihrer Zuhörer rückgängig zu machen und sobald Ihre Arbeit fertig ist, registrieren Sie sie erneut? Klingt für mich wie eine AsyncTask.

+0

Das ist nicht möglich. Hörer könnten überall sein und die App könnte in jedem Zustand sein. Die Änderungen an der Datenbank werden in einem Remote-Dienst vorgenommen. Außerdem glaube ich nicht, dass es möglich ist, Beobachter eines SimpleCursorTreeAdapters abzumelden, was bedeutet, dass ich einen benutzerdefinierten Adapter erstellen musste. – Tom

+0

Ist das alles in Ihrer eigenen Anwendung? –

+0

Sorry zu schnell für den letzten Kommentar gesendet. Haben Sie darüber nachgedacht, einen weiteren Beobachter hinzuzufügen, ob eine Client-Klasse zuhören soll oder nicht, und Sie könnten auch versuchen, die schwere db-Arbeit über SQLite direkt auszuführen und einfach einen 1 = 1-Update-Aufruf zu senden, wenn Sie fertig sind. –

Verwandte Themen