Je vois souvent du code qui implique d'itérer sur le résultat d'une requête de base de données, de faire quelque chose avec chaque ligne, puis de passer à la ligne suivante. Les exemples typiques sont les suivants.
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());
}
Tout cela me semble excessivement long, chacun avec de multiples appels aux Cursor
méthodes. Il doit sûrement y avoir un moyen plus soigné?
Réponses:
La façon la plus simple est la suivante:
Le curseur commence avant la première ligne de résultat, donc à la première itération, il passe au premier résultat s'il existe . Si le curseur est vide ou si la dernière ligne a déjà été traitée, la boucle se termine proprement.
Bien sûr, n'oubliez pas de fermer le curseur une fois que vous en avez terminé, de préférence dans une
finally
clause.Si vous ciblez l'API 19+, vous pouvez utiliser try-with-resources.
la source
CursorLoader
, assurez-vous d'appelercursor.moveToPosition(-1)
avant l'itération, car le chargeur réutilise le curseur lorsque l'orientation de l'écran change. J'ai passé une heure à rechercher ce problème!La meilleure façon que j'ai trouvée de passer par un curseur est la suivante:
N'oubliez pas de fermer le curseur par la suite
EDIT: La solution donnée est idéale si vous avez besoin d'itérer un curseur dont vous n'êtes pas responsable. Un bon exemple serait, si vous prenez un curseur comme argument dans une méthode, et que vous devez scanner le curseur pour une valeur donnée, sans avoir à vous soucier de la position actuelle du curseur.
la source
Je voudrais juste souligner une troisième alternative qui fonctionne également si le curseur n'est pas à la position de départ:
la source
moveToPosition(-1)
. Ainsi, les deux réponses sont également concises car elles ont toutes deux deux appels de curseur. Je pense que cette réponse tranche juste la réponse de Borland car elle ne nécessite pas le-1
nombre magique.Que diriez-vous d'utiliser la boucle foreach:
Cependant ma version de CursorUtils devrait être moins laide, mais elle ferme automatiquement le curseur:
la source
Cursor
instance à chaque itération de la boucle.Ci-dessous pourrait être le meilleur moyen:
Le code ci-dessus garantirait qu'il passerait par une itération entière et n'échapperait pas à la première et à la dernière itération.
la source
Exemple de code:
la source
iterator()
devrait également recalculertoVisit = cursor.getCount();
j'utiliseclass IterableCursor<T extends Cursor> implements Iterable<T>, Iterator<T> {...
qui reçoit une classeextends CursorWrapper implements MyInterface
où MyInterface définit des getters pour les propriétés de la base de données. De cette façon, j'ai un itérateur basé sur le curseur <MyInterface>La solution Do / While est plus élégante, mais si vous utilisez uniquement la solution While publiée ci-dessus, sans le moveToPosition (-1), vous manquerez le premier élément (au moins sur la requête Contact).
Je suggère:
la source
la source
Le curseur est l'interface qui représente une
2-dimensional
table de n'importe quelle base de données.Lorsque vous essayez de récupérer des données à l'aide d'une
SELECT
instruction, la base de données crée d'abord un objet CURSOR et vous renvoie sa référence.Le pointeur de cette référence renvoyée pointe vers le 0ème emplacement qui est autrement appelé comme avant le premier emplacement du curseur. moveToFirst
Lorsque vous appelez la
moveToFirst()
méthode sur le curseur, il place le pointeur du curseur au premier emplacement. Vous pouvez maintenant accéder aux données présentes dans le 1er enregistrementLa meilleure façon de regarder:
Curseur du curseur
la source
Initialement, le curseur n'est pas sur la première ligne à l'aide de
moveToNext()
vous pouvez itérer le curseur lorsque l'enregistrement n'existe pas, alorsreturn false
, à moins que celareturn true
,la source