Verwendung von Cursor mit ListView-Adapter für eine große Datenmenge

7

Ich verwende einen benutzerdefinierten CursorAdapter, um Daten aus einer SQLite-Datenbank abzurufen und sie in einer Listenansicht anzuzeigen. Die Datenbank enthält zwei Spalten mit etwa 8.000 Zeilen. also suche ich nach einer Möglichkeit, alle Daten so schnell wie möglich abzufragen und anzuzeigen. Ich habe dies mit asyncTask getan, hier ist der Code:

%Vor%

}

das funktioniert gut außer dem Teil, wenn ich das Ergebnis in einen Adapter setzen muss. Ich habe einige Zeittests gemacht und es dauert ungefähr 700 ms, um es über den StartManagingCursor hinaus zu schaffen. Das Problem ist, dass es etwa 7 Sekunden dauert, um es über setAdapter (result) zu setzen, und dies wird im UI-Thread ausgeführt, sodass meine App nicht mehr reagiert (der Fortschrittsdialog bleibt stehen und macht manchmal die App). Wie mache ich diese Zeit weniger? Kann ich dies auch im Hintergrund oder auf andere Weise machen, um die Reaktionsfähigkeit zu erhöhen?

tnx.

%Vor%     
DArkO 02.12.2010, 00:28
quelle

4 Antworten

25

Der Grund für die langsame Zeit beim Laden des Adapters ist der interne Aufruf des CursorAdapter an Cursor.getCount ().

Cursor in Android sind faul geladen. Die Ergebnisse werden erst geladen, wenn sie benötigt werden. Wenn der CursorAdapter getCount () aufruft, wird die Abfrage vollständig ausgeführt und die Ergebnisse werden gezählt.

Unten sind ein paar Links, die genau dieses Problem diskutieren.

Ссылка

Ссылка

Mein Vorschlag wäre, Ihre Anfrage aufzuteilen. Laden Sie nur die Anzahl der sichtbaren Listenelemente auf dem Bildschirm. Während der Benutzer scrollt, laden Sie den nächsten Satz. Sehr ähnlich den GMail und Market Anwendungen. Leider habe ich kein praktisches Beispiel: (

Dies beantwortet Ihre Frage nicht, aber hoffentlich gibt es einen Einblick:)

    
Jason L. 02.12.2010, 02:58
quelle
3
___ qstntxt ___

Ich verwende einen benutzerdefinierten CursorAdapter, um Daten aus einer SQLite-Datenbank abzurufen und sie in einer Listenansicht anzuzeigen. Die Datenbank enthält zwei Spalten mit etwa 8.000 Zeilen. also suche ich nach einer Möglichkeit, alle Daten so schnell wie möglich abzufragen und anzuzeigen. Ich habe dies mit asyncTask getan, hier ist der Code:

%Vor%

}

das funktioniert gut außer dem Teil, wenn ich das Ergebnis in einen Adapter setzen muss. Ich habe einige Zeittests gemacht und es dauert ungefähr 700 ms, um es über den StartManagingCursor hinaus zu schaffen. Das Problem ist, dass es etwa 7 Sekunden dauert, um es über setAdapter (result) zu setzen, und dies wird im UI-Thread ausgeführt, sodass meine App nicht mehr reagiert (der Fortschrittsdialog bleibt stehen und macht manchmal die App). Wie mache ich diese Zeit weniger? Kann ich dies auch im Hintergrund oder auf andere Weise machen, um die Reaktionsfähigkeit zu erhöhen?

tnx.

%Vor%     
___ antwort4330845 ___

Nicht sicher, warum setAdapter so lange dauern sollte. Ich habe etwa 5000 Reihen viel schneller gemacht. Normalerweise erzeuge ich jedoch zuerst einen Adapter ohne einen Cursor, rufe setAdapter mit dem "leeren" Adapter auf und starte dann eine asynchrone Abfrage mit einer AsyncQueryHandler-Unterklasse. In OnQueryComplete rufe ich changeCursor dann auf dem Adapter auf.

    
___ answer4331266 ___

Der Grund für die langsame Zeit beim Laden des Adapters ist der interne Aufruf des CursorAdapter an Cursor.getCount ().

Cursor in Android sind faul geladen. Die Ergebnisse werden erst geladen, wenn sie benötigt werden. Wenn der CursorAdapter getCount () aufruft, wird die Abfrage vollständig ausgeführt und die Ergebnisse werden gezählt.

Unten sind ein paar Links, die genau dieses Problem diskutieren.

Ссылка

Ссылка

Mein Vorschlag wäre, Ihre Anfrage aufzuteilen. Laden Sie nur die Anzahl der sichtbaren Listenelemente auf dem Bildschirm. Während der Benutzer scrollt, laden Sie den nächsten Satz. Sehr ähnlich den GMail und Market Anwendungen. Leider habe ich kein praktisches Beispiel: (

Dies beantwortet Ihre Frage nicht, aber hoffentlich gibt es einen Einblick:)

    
___ answer4330838 ___

Nun, ich kann Ihnen an dieser Stelle nur einen dummen Vorschlag anbieten - beginnen Sie eine Abfrage in einem separaten Thread, der durch die gesamte Datenbank geht und Ihren 8000-Zeilen-Cursor erstellt.

Erstellen Sie in Ihrem UI-Thread einen Cursor, für den Sie das Limit auf 100 oder so festlegen, und verwenden Sie diesen für Ihren Adapter. Wenn der Benutzer zum Ende der Liste scrollt, können Sie eine Zeile mit einer ProgressBar hinzufügen oder angeben, dass weitere Elemente hinzugefügt werden sollen.

Wenn der zweite Thread fertig ist, ersetzen Sie den Adapter.

Alternativ können Sie einen Array-Adapter oder etwas Ähnliches verwenden. Führen Sie im zweiten Thread jeweils eine Reihe von Abfragen mit jeweils 100 Zeilen aus, und fügen Sie sie zu Ihrem Array-Adapter hinzu, wenn sie eintreffen Dummy-Reihe am unteren Rand, die den Benutzern sagt, dass sie ihre Pferde halten sollen.

Eine Anmerkung - Ich würde annehmen, dass es sicher ist, aus zwei Threads gleichzeitig aus der Datenbank zu lesen, aber sei vorsichtig, wenn es um das Schreiben geht. Meine App hatte einen wundervollen Bug, bei dem die Datenbank zerstört wurde, als ich Datenbankoperationen in einem separaten Thread hatte, bis ich die korrekte Sperrung hinzugefügt hatte (die Sie auch in der Datenbank aktivieren können).

EDIT: Natürlich, AsyncQueryHandler, ich wusste, dass da so etwas war, aber ich konnte mich nicht an den Namen erinnern. Eleganter als ein separater Thread, natürlich.

Übrigens - wie speichern Sie die Datenbank? Ist es nur eine normale Datenbankdatei in Ihrem internen Speicher?

    
___ qstnhdr ___ Verwendung von Cursor mit ListView-Adapter für eine große Datenmenge ___ tag123database ___ Eine Datenbank ist eine organisierte Sammlung von Daten. Es ist die Sammlung von Schemas, Tabellen, Abfragen, Berichten, Ansichten und anderen Objekten. Die Daten sind typischerweise so organisiert, dass sie Aspekte der Realität so modellieren, dass sie Prozesse unterstützen, die Informationen benötigen. Verwenden Sie dieses Tag, wenn Sie Fragen zum Entwerfen einer Datenbank haben. Wenn es sich um ein bestimmtes Datenbankverwaltungssystem (z. B. MySQL) handelt, verwenden Sie stattdessen dieses Tag. ___ tag123android ___ Android ist das mobile Betriebssystem von Google, das zum Programmieren oder Entwickeln von digitalen Geräten (Smartphones, Tablets, Automobile, Fernseher, Wear, Glass, IoT) verwendet wird. Verwenden Sie für Themen rund um Android Android-spezifische Tags wie android-intent, nicht intent, android-activity, nicht activity, android-adapter, nicht adapter usw. Bei anderen Fragen als der Entwicklung oder Programmierung, aber im Zusammenhang mit Android Framework, verwenden Sie Der Link: https://android.stackexchange.com. ___ tag123adapter ___ Ein Entwurfsmuster, das mehrere Schnittstellen über eine gemeinsame Schnittstelle oder Klasse kompatibel macht. Einer der strukturellen Entwurfsmuster der Gruppe der vier. ___ tag123listview ___ Ein ListView ist ein grafisches Screen Control oder Widget, das von UI-Bibliotheken in den meisten modernen Betriebssystemen bereitgestellt wird, um Elemente in Listenform anzuzeigen. ___ answer16871598 ___

Hi im Versuch, dies mit mehr als 50000rows zu erreichen. Ich denke, dass mein Code Ihnen die besseren Ergebnisse für Sie geben kann, da Sie nur 8000 Datensätze haben.

1) Verwenden Sie den Inhaltsanbieter anstelle von sqlite. 2) Verwenden Sie LoaderManager-Callbacks, um den Cursor asynchron zu laden 3) zum Suchen verwenden Sie FTS-Tabellen. 4) Optimieren Sie Ihre Datenbank mit Indexierung auch.

vertrau mir, es funktioniert sehr gut mit 8000 Zeilen auch mit sectionIndexer und mit schnell scrollen auch.

lassen Sie mich wissen, wenn Sie irgendwelche Zweifel haben.

Ps. Wenn Sie eine bessere Lösung gefunden haben, die 50000 Zeilen verarbeiten kann, lassen Sie es mich wissen.

    
___
dhaag23 02.12.2010 01:23
quelle
2

Nun, ich kann Ihnen an dieser Stelle nur einen dummen Vorschlag anbieten - beginnen Sie eine Abfrage in einem separaten Thread, der durch die gesamte Datenbank geht und Ihren 8000-Zeilen-Cursor erstellt.

Erstellen Sie in Ihrem UI-Thread einen Cursor, für den Sie das Limit auf 100 oder so festlegen, und verwenden Sie diesen für Ihren Adapter. Wenn der Benutzer zum Ende der Liste scrollt, können Sie eine Zeile mit einer ProgressBar hinzufügen oder angeben, dass weitere Elemente hinzugefügt werden sollen.

Wenn der zweite Thread fertig ist, ersetzen Sie den Adapter.

Alternativ können Sie einen Array-Adapter oder etwas Ähnliches verwenden. Führen Sie im zweiten Thread jeweils eine Reihe von Abfragen mit jeweils 100 Zeilen aus, und fügen Sie sie zu Ihrem Array-Adapter hinzu, wenn sie eintreffen Dummy-Reihe am unteren Rand, die den Benutzern sagt, dass sie ihre Pferde halten sollen.

Eine Anmerkung - Ich würde annehmen, dass es sicher ist, aus zwei Threads gleichzeitig aus der Datenbank zu lesen, aber sei vorsichtig, wenn es um das Schreiben geht. Meine App hatte einen wundervollen Bug, bei dem die Datenbank zerstört wurde, als ich Datenbankoperationen in einem separaten Thread hatte, bis ich die korrekte Sperrung hinzugefügt hatte (die Sie auch in der Datenbank aktivieren können).

EDIT: Natürlich, AsyncQueryHandler, ich wusste, dass da so etwas war, aber ich konnte mich nicht an den Namen erinnern. Eleganter als ein separater Thread, natürlich.

Übrigens - wie speichern Sie die Datenbank? Ist es nur eine normale Datenbankdatei in Ihrem internen Speicher?

    
EboMike 02.12.2010 01:21
quelle
1

Hi im Versuch, dies mit mehr als 50000rows zu erreichen. Ich denke, dass mein Code Ihnen die besseren Ergebnisse für Sie geben kann, da Sie nur 8000 Datensätze haben.

1) Verwenden Sie den Inhaltsanbieter anstelle von sqlite. 2) Verwenden Sie LoaderManager-Callbacks, um den Cursor asynchron zu laden 3) zum Suchen verwenden Sie FTS-Tabellen. 4) Optimieren Sie Ihre Datenbank mit Indexierung auch.

vertrau mir, es funktioniert sehr gut mit 8000 Zeilen auch mit sectionIndexer und mit schnell scrollen auch.

lassen Sie mich wissen, wenn Sie irgendwelche Zweifel haben.

Ps. Wenn Sie eine bessere Lösung gefunden haben, die 50000 Zeilen verarbeiten kann, lassen Sie es mich wissen.

    
oops.objective 01.06.2013 10:16
quelle

Tags und Links