6

Ich habe ein halb kompliziertes Problem und hoffe, dass jemand hier in der Lage sein wird, mir zu helfen.Android: notifyDataSetChanged() nicht listview nach der Orientierung ändern

Bei einem Klickereignis erstelle ich einen Thread und starte eine lang andauernde Operation basierend auf this Methode. Nachdem die lang andauernde Aufgabe abgeschlossen ist, hat es einen Rückruf an eine andere Methode, die einen Beitrag an die Prozedur tut:

@Override 
public void contentSearchModelChanged(Model_ContentSearch csm, ArrayList<Class_Reminder> newRemindersList) { 
    remindersList = newRemindersList; 
    mHandler.post(mUpdateDisplayRunnable); 
} 

, die einen Runnable nennt:

// post this to the Handler when the background thread completes 
private final Runnable mUpdateDisplayRunnable = new Runnable() { 
    public void run() { 
    updateDisplay(); 
    } 
}; 

Schließlich, was, hier ist mein updateDisplay() Methode macht:

private void updateDisplay() { 
    if (csModel.getState() != Model_ContentSearch.State.RUNNING) { 
     if(remindersList != null && remindersList.size() > 0){ 
       r_adapter = new ReminderAdapater(Activity_ContentSearch.this, remindersList, thisListView); 
       thisListView.setAdapter(r_adapter); 
       r_adapter.notifyDataSetChanged(); 
     } 
    } 
} 

Dies funktioniert wunderbar, wenn ich das normalerweise mache. Wenn ich jedoch die Ausrichtung ändere, während der lang andauernde Vorgang ausgeführt wird, funktioniert es nicht. Es macht den Rückruf richtig, und die remindersList enthält Elemente. Aber wenn es zu dieser Zeile kommt:

r_adapter.notifyDataSetChanged(); 

Nichts passiert. Das Seltsame ist, wenn ich ein anderes Submit mache und es den ganzen Prozess wieder laufen lasse (ohne die Orientierung zu ändern), aktualisiert es tatsächlich die Ansicht zweimal, einmal für das vorherige Submit und wieder für das nächste. So wird die Ansicht einmal mit den Ergebnissen der ersten Vorlage aktualisiert, dann erneut mit den Ergebnissen der zweiten Vorlage eine Sekunde später. Der ADAPATER DID bekommt also die Daten, es aktualisiert die Ansicht nicht.

Ich weiß, das hat etwas mit der Orientierung Änderung zu tun, aber ich kann nicht für das Leben von mir herausfinden, warum. Kann jemand helfen? Oder kann jemand eine alternative Methode vorschlagen, Threads mit Orientierungsänderungen zu behandeln?

Bara

Antwort

6

Das Problem ist, dass, wenn Sie Orientierungen eine neue Aktivität zu ändern ist von Anfang an hochgedreht (onCreate). Ihr lang laufender Prozess hat einen Griff zur alten (nicht mehr sichtbaren) Aktivität. Sie aktualisieren die alte Aktivität ordnungsgemäß, aber da sie nicht mehr auf dem Bildschirm angezeigt wird, sehen Sie sie nicht.

Dies ist kein einfaches Problem zu beheben. Es gibt eine Bibliothek, die Ihnen helfen kann. Es heißt DroidFu. Hier ist eine Blog-Post, dass (viel genauer als I) beschreibt die Ursache, was Sie sehen und wie die DroidFu Bibliothek bekämpft es: http://brainflush.wordpress.com/2009/11/16/introducing-droid-fu-for-android-betteractivity-betterservice-and-betterasynctask/

Edit: (Hinzufügen von Code für die Verfolgung von aktiver Aktivität)

In dies Ihre Anwendungsklasse:

private Activity _activeActivity; 
public void setActiveActivity(Activity activity) { 
    _activeActivity = activity; 
} 
public Activity getActiveActivity() { 
    return _activeActivity; 
} 

In Ihrer Aktivitäten, fügen Sie diese:

@Override 
public void onResume() { 
    super.onResume(); 
    ((MyApplicationClassName)getApplication()).setActiveActivity(this); 
} 

Jetzt können Sie die aktive activi bekommen ty durch Aufruf von MyApplicationClassName.getActiveActivity();

Dies ist nicht, wie DroidFu es tut. DroidFu legt die aktive Aktivität in onCreate fest, aber ich halte das nicht für sehr robust.

+0

Hmm ... das scheint sehr hilfreich zu sein, aber es scheint nicht viel Dokumentation zu sein? Ich würde es hassen, meine Implementierung auf DroidFu umzustellen und nicht zu wissen, wie man ein Problem löst, weil es nicht die "typische" Art ist, Dinge zu tun. – Bara

+0

Ja, es scheint eine alte verlassene Bibliothek zu sein, aber die Prämisse scheint solide zu sein. Sie könnten dies tun, ohne die Bibliothek zu benutzen. Grundsätzlich verfolgt das Application-Objekt die aktive Aktivität (mit onResume). Wenn Sie dann bereit sind, Ihren Adapter zu benachrichtigen, erhalten Sie die aktive Aktivität aus der Anwendung, überprüfen Sie, ob es sich um eine Instanz Ihrer erwarteten Aktivität handelt, und falls ja, umsetzen und benachrichtigen. –

+0

Was genau ist der Code zum Verfolgen der "aktiven Aktivität"? Das heißt, sollte ich etwas tun wie CurrentActivity act = new CurrentActivity(); dann übergeben Sie die Aktion an die Application-Klasse? – Bara

1

Ich hatte ein ähnliches Problem, mit einem zeitaufwendigen Thread sendEmptyMessage zu einem Handler, der wiederum notifyDataSetChanged auf einem ListAdapter aufgerufen. Es funktionierte gut, bis ich die Orientierung änderte.

Ich löste es, indem ich einen zweiten Handler im UI-Thread deklarierte und den ersten Handler sendEmptyMessage zu diesem Handler machte, der seinerseits notifyDataSetChanged auf dem ListAdapter anrief. Und den ListAdapter als statisch deklariert haben.

Ich bin ein Neuling, damit ich weiß nicht, ob es eine hässliche Lösung, aber es funktioniert für mich ...

Von Jere.Jones Beschreibung würde ich davon ausgehen, das funktioniert so: Der langen laufenden Prozess sendEmptyMessage an das Handle aus der alten Aktivität, die sendEmptyMessage wiederum an das Handle in der neuen Aktivität sendet.