Ist ArrayAdapter thread-safe in android? Wenn nicht, was kann ich tun, um es thread-sicher?
Können sagen, ich erweitern ArrayAdapter
und in den code, wo ich bin übergeordnete getView(int i, View v, ViewGroup g)
, ich erfrage das aktuelle Element mit getItem(i)
. Kann ich sicher sein, dass getItem(i)
wird ein Produkt zurück, auch wenn die anderen threads manipulieren, die der selben ArrayAdapter
?
Ich bin mir nicht sicher, aber ich denke, die Antwort ist Nein. Wenn es ist, was empfehlen Sie ich tun, um es thread-safe?
Du musst angemeldet sein, um einen Kommentar abzugeben.
Es ist nicht eine Frage der ArrayAdapter wird der Faden sicher. ListView und andere UI-widgets, die funktionieren mit einem Adapter erlauben nicht den Inhalt des Adapters zu ändern, der unerwartet auf Sie. Und das ist mehr, als nur aufgrund der anderen threads -- man muss sagen, die ListView über die änderung, die Sie machen, bevor es weiter versucht die Interaktion mit dem adapter.
Wenn Sie zulassen, dass einem anderen thread ändern Sie den adapter, oder ändern Sie ihn auf dem Haupt-thread aber nicht sagen, ListView über die änderung vor, dass etwas anderes passieren, werden Sie nach dem Zufallsprinzip (durch Rennen) Ausnahmen, die ausgelöst durch ListView über den adapter ändern sich unerwartet.
In dem speziellen Fall von ArrayAdapter wenn Sie die API verwenden, zu ändern, deren Inhalt es wird dafür sorgen, zu sagen, die Liste Ansicht über die Veränderung. Aber Sie muss solche änderungen auf der main-thread, um sicherzustellen, dass die Liste Ansicht nicht versuchen, Zugriff auf den adapter zwischen dem Punkt, wo Sie Ihre änderungen vorgenommen und die Listen-Ansicht wird erzählt, dass zu ändern.
Wenn Sie sind nur einfache änderungen an ArrayAdapter (hinzufügen und entfernen von ein paar Sachen), dann werden Sie in Ordnung sein, aber Sie müssen diese auf dem Haupt-thread.
Weitere signifikante änderungen (wie sagen die adapter immer ein neues data-set durch ein abrufen der neuen Daten von einem server), Sollten nicht unter Verwendung ArrayAdapter und stattdessen die Realisierung Ihrer eigenen Unterklasse von BaseAdapter. ArrayAdapter ist gedacht für Situationen, in denen man eine kleine einfache Recht statischen set von Daten zu zeigen, - einfache Situationen. Für kompliziertere Dinge wirst du wahrscheinlich glücklicher sein, nur die Umsetzung BaseAdapter und dabei das Daten-management selbst.
Den typischen Weg eines Adapters updates in diesen komplizierten Situationen ist, dass ein hintergrund-thread erzeugt die neue Datei, und sobald er verfügbar ist dann auf der main-thread ist es vertauscht in den adapter atomar mit einem Aufruf notifyDataSetChanged() auf, damit die ListView wissen, dass die Daten geändert hat.
Sagen wir also, dass Sie zeigen einige Daten, dass ist ein array von MyItem Objekte. Halten Sie Ihre Daten in eine Spiel-Reihe:
Implementieren Sie eine Unterklasse von BaseAdapter das zeigt diese Liste:
Und hier ist nun eine Funktion, die Sie durchführen könnten die auf die adapter von einem anderen thread aufgerufen, um einen neuen Daten-Satz gezeigt werden:
Natürlich, wenn Sie mit AsyncTask, um Ihre Daten generation verfügt bereits über eine praktische Einrichtung für die Durchführung, die Arbeit zurück auf den Haupt-thread. Ebenso könnten Sie die neue Loader-Anlage kümmern sich um die generation in den hintergrund.
Und wenn Sie noch verwenden möchten ArrayAdapter, in Ihrer Funktion oben könnten Sie tun dies durch das löschen der aktuellen Daten und dem hinzufügen der neuen Daten in die jetzt leere-adapter. Dies ist nur mehr-Aufwand, der nicht wirklich gewinnen Sie nichts.
Array-Adapter ist nicht thread-sicher. Ich habe es gesehen-crash aufgrund von parallelitätsproblemen. Der array-adapter nur übersetzen Sie Ihre array auf einen Blick auf dem main (GUI) Threads. Also, wenn Sie sind vorsichtig, immer nur ändern, array (hinzufügen oder löschen) auf der main-thread, dann können Sie es sicherstellen, dass nur jeder Lauf auf 1 thread.