2014-10-27 10 views
10

Ich habe viele Beispiele/Tutorials zur Verwendung von SQLite in Android durchgesehen. Nehmen wir an, Sie haben eine App, die SQLite, ContentProvider, CursorLoader, eine benutzerdefinierte CursorAdapter verwendet. Jetzt alle wichtigen Beispiele dafür, die ich gefunden habe, verlassen sich auf eine CursorLoader, um Daten an die CursorAdapter zu holen, die durch die Art von CursorLoader passiert in einer Async - UI thread sichere Art und Weise. Diese gleichen Beispiele machen jedoch alle das Einfügen/Löschen/Aktualisieren von Anrufen über die ContentResolver auf dem Hauptthread (z. B. von onClick, onResume,). (Example) Sie wickeln diese Anrufe nicht in eine AsyncTask oder starten Sie einen separaten Thread oder verwenden Sie AsyncQueryHandler. Warum können so viele gut geschriebene Blogs/Beispiele einen so offensichtlichen Fehler machen? Oder sind einfache Einfüge-/Lösch-/Aktualisierungsanrufe so einfach, dass sie sicher genug vom Main/UI-Thread gestartet werden können? Was ist der richtige Weg, um diese schnellen Anrufe zu tätigen?Android - SQLite ContentResolver einfügen/löschen/update auf UI Thread?

+1

Ihr letzter Satz ist wahrscheinlich richtig: Abfragevorgang ist sicherlich viel komplexer als einzelne einfügen/aktualisieren/löschen – pskink

Antwort

4

Ich war auch verwirrt über die Proben, die Anrufe auf dem Hauptthread. Ich nehme an, dass die Beispiele die Demonstrationen vereinfacht haben und zusätzliche Threads und Callbacks vermieden haben, da der einzelne Einfüge-/Aktualisierungs-/Lösch-Aufruf möglicherweise schnell zurückkehrt.

Neben dem Loader-Muster für die Abfrage bietet Android eine Hilfsklasse AsyncQueryHandler, seit API-Ebene 1, für asynchrone CRUD-Operationen mit vollständigen CRUD-Callbacks unterstützt. Der AsyncQueryHandler arbeitet mit einem HandlerThread für die asynchronen Operationen zusammen und liefert die Ergebnisse an den Hauptthread zurück.

Ich glaube also, dass die ContentProvider-Abfragen in anderen Worker-Threads als der Benutzeroberfläche ausgeführt werden sollten, und diese Beispiele entsprechen möglicherweise nicht den Best Practices gemäß dem offiziellen Design.

=== bearbeiten

eine Anmerkung von den offiziellen Rahmen docs gefunden, siehe this oder this, Linie 255:

In practice, this should be done in an asynchronous thread instead of 
on the main thread. For more discussion, see Loaders. If you are not 
just reading data but modifying it, see {@link android.content.AsyncQueryHandler}. 

=== bearbeiten 2 Link zu eigentliche Führung android dev enthält, die über Zitat

+0

Richtig, ich erwähnte den AsyncQueryHandler in meiner Frage auch ... es ist immer noch nicht sehr überzeugend, dass alle Tutorials und Beispiele, die ich gekommen bin across dies tun, nur weil es einfacher ist und nicht einmal erwähnen, dass dies nicht ist, wie Sie es tun sollten. Für eine korrekte Antwort möchte ich entweder etwas offizielles von Google (Teammitglied, Dokument, Tutorial) oder etwas in dieser Richtung (vielleicht eine Verbindung zu einem respektablen GitHub Projekt, das dies in der einen oder anderen Weise tut), die diese leichten Anrufe auf der Main Thread, oder verwendet so etwas wie AsyncQueryHandler ... –

+0

Ansonsten ist alles andere nur unsere Meinung zu diesem ... :) –

+0

@LeOK Got ein offizielles Dokument, das dies erwähnt. Bitte sehen Sie meine Änderungen. –

2

Diese Frage beschäftigt mich seit langer Zeit. Ich denke, das hängt von der Komplexität der Datei ab, die wir einfügen, aktualisieren oder löschen möchten. Wenn unsere Anwendung große Dateien einfügt oder aktualisiert, wäre es immer richtig, sie asynchron auszuführen, und wenn die Dateien nicht so groß werden, kann sie auf dem UI-Thread ausgeführt werden.

Es wird jedoch immer empfohlen, mit Datenbankoperationen in einem separaten Thread fortzufahren.

+0

Danke für die Antwort. Dies erklärt nicht wirklich, warum Tutorials, die Best Practices und andere Facetten erklären, Dinge richtig/sicher tun, im Fall von Einfügen/Löschen/Aktualisieren sich nie mit separaten Threads befassen. Natürlich habe ich nicht alle guten Tutorials gelesen, daher wären einige gute Gegenbeispiele willkommen. (Insbesondere solche von Google oder anderen seriösen Quellen) –

0

Ich denke, Sie haben Ihre eigene Frage beantwortet. Ich glaube, dass CursorLoader AsyncTaskLoader erweitert. Aufrufe aus dem UI-Thread verarbeiten nur den Aufruf TO CusorLoader (der AsyncTask verwendet). Was durch den Aufruf geschieht, tritt immer noch nicht auf dem UI-Thread auf. Ein Aufruf einer Methode/Funktion, die dann Dinge in einem separaten Thread ausführt, macht immer noch Arbeit außerhalb des UI-Threads.

Welche Arbeit wird auf dem UI-Thread ausgeführt?

Bitte zeigen Sie Debug-Protokoll, wenn möglich oder Beispiel, wo Sie denken, dass Arbeit auf UI getan wird. Es sollte nicht sein.

Sie wollen nicht streiten, wollen nur wissen, wie Sie zum Abschluss der UI-Arbeit gekommen sind?

+0

Sie haben recht, wenn der Cursor loader asynchron ist. Das habe ich mir selbst in der Frage geschrieben. Die Aufrufe zum Einfügen/Löschen/Aktualisieren werden jedoch über den ContentReslover und nicht über CursorLoader ausgeführt. Alles, was ContentReslover durchläuft, wird im UI-Thread ausgeführt, wenn der Aufruf im UI-Thread erfolgt. Dies lässt sich leicht überprüfen, indem einfach ein Thread.sleep (5000) am Anfang der Einfügeüberschreibung Ihres ContentProviders hinzugefügt wird. Wenn Sie dies tun, sehen Sie Ihre Benutzeroberfläche für 5 Sekunden eingefroren ... –