Ich sehe häufig Code, bei dem das Ergebnis einer Datenbankabfrage durchlaufen wird, mit jeder Zeile etwas getan wird und dann mit der nächsten Zeile fortgefahren wird. Typische Beispiele sind wie folgt.
Cursor cursor = db.rawQuery(...);
cursor.moveToFirst();
while (cursor.isAfterLast() == false)
{
...
cursor.moveToNext();
}
Cursor cursor = db.rawQuery(...);
for (boolean hasItem = cursor.moveToFirst();
hasItem;
hasItem = cursor.moveToNext()) {
...
}
Cursor cursor = db.rawQuery(...);
if (cursor.moveToFirst()) {
do {
...
} while (cursor.moveToNext());
}
Diese scheinen mir alle übermäßig langwierig zu sein, jeder mit mehreren Cursor
Methodenaufrufen. Sicherlich muss es einen saubereren Weg geben?
Antworten:
Der einfachste Weg ist folgender:
Der Cursor startet vor der ersten Ergebniszeile. Bei der ersten Iteration wird zum ersten Ergebnis gewechselt, falls vorhanden . Wenn der Cursor leer ist oder die letzte Zeile bereits verarbeitet wurde, wird die Schleife ordnungsgemäß beendet.
Vergessen Sie natürlich nicht, den Cursor zu schließen, wenn Sie damit fertig sind, vorzugsweise in einer
finally
Klausel.Wenn Sie auf API 19+ abzielen, können Sie Try-with-Resources verwenden.
quelle
CursorLoader
, stellen Sie sicher, dass Siecursor.moveToPosition(-1)
vor dem Iterieren aufrufen , da der Loader den Cursor wiederverwendet, wenn sich die Bildschirmausrichtung ändert. Wir haben eine Stunde damit verbracht, dieses Problem aufzuspüren!Der beste Weg, den ich gefunden habe, um durch einen Cursor zu gehen, ist der folgende:
Vergessen Sie nicht, den Cursor danach zu schließen
BEARBEITEN: Die angegebene Lösung ist großartig, wenn Sie jemals einen Cursor iterieren müssen, für den Sie nicht verantwortlich sind. Ein gutes Beispiel wäre, wenn Sie einen Cursor als Argument in einer Methode verwenden und den Cursor nach einem bestimmten Wert durchsuchen müssen, ohne sich um die aktuelle Position des Cursors kümmern zu müssen.
quelle
Ich möchte nur auf eine dritte Alternative hinweisen, die auch funktioniert, wenn sich der Cursor nicht an der Startposition befindet:
quelle
moveToPosition(-1)
. Beide Antworten sind also gleichermaßen konsistent, da beide zwei Cursoraufrufe haben. Ich denke, diese Antwort übertrifft Borlands Antwort nur, da sie nicht die-1
magische Zahl erfordert .Wie wäre es mit foreach loop:
Meine Version von CursorUtils sollte jedoch weniger hässlich sein, schließt jedoch automatisch den Cursor:
quelle
Cursor
in jeder Iteration der Schleife dieselbe Instanz verwenden.Unten könnte der bessere Weg sein:
Der obige Code würde sicherstellen, dass er die gesamte Iteration durchläuft und nicht der ersten und letzten Iteration entgeht.
quelle
Beispielcode:
quelle
iterator()
sollte auch neu berechnentoVisit = cursor.getCount();
Ich verwende,class IterableCursor<T extends Cursor> implements Iterable<T>, Iterator<T> {...
dass eine Klasse empfängt,extends CursorWrapper implements MyInterface
in der MyInterface Getter für Datenbankeigenschaften definiert. Auf diese Weise habe ich einen Cursor-basierten Iterator <MyInterface>Die Do / While-Lösung ist eleganter, aber wenn Sie nur die oben angegebene While-Lösung verwenden, wird ohne die moveToPosition (-1) das erste Element übersehen (zumindest in der Kontaktabfrage).
Ich schlage vor:
quelle
quelle
Der Cursor ist die Schnittstelle, die eine
2-dimensional
Tabelle einer beliebigen Datenbank darstellt.Wenn Sie versuchen, einige Daten mithilfe einer
SELECT
Anweisung abzurufen , erstellt die Datenbank zunächst ein CURSOR-Objekt und gibt dessen Referenz an Sie zurück.Der Zeiger dieser zurückgegebenen Referenz zeigt auf die 0. Stelle die ansonsten wie vor der ersten Position des Cursors aufgerufen wird. Wenn Sie also Daten vom Cursor abrufen möchten, müssen Sie zuerst zum 1. Datensatz wechseln, damit wir sie verwenden können moveToFirst
Wenn Sie eine
moveToFirst()
Methode für den Cursor aufrufen , wird der Cursorzeiger an die erste Stelle geführt. Jetzt können Sie auf die im 1. Datensatz vorhandenen Daten zugreifenDer beste Weg, um zu schauen:
Cursor Cursor
quelle
Am Anfang Cursor ist nicht auf der ersten Zeile zeigt mit
moveToNext()
den Cursor durchlaufen kann , wenn Datensatz nicht existiert dannreturn false
, wenn sie nichtreturn true
,quelle