Frecuentemente veo código que implica iterar sobre el resultado de una consulta a la base de datos, hacer algo con cada fila y luego pasar a la siguiente fila. Ejemplos típicos son los siguientes.
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());
}
Todo esto me parece excesivamente largo, cada uno con múltiples llamadas a Cursor
métodos. Seguramente debe haber una manera más ordenada?
Respuestas:
La forma más simple es esta:
El cursor comienza antes de la primera fila de resultados, por lo que en la primera iteración se mueve al primer resultado si existe . Si el cursor está vacío, o la última fila ya ha sido procesada, entonces el bucle sale de manera ordenada.
Por supuesto, no olvide cerrar el cursor una vez que haya terminado, preferiblemente en una
finally
cláusula.Si apunta a API 19+, puede usar try-with-resources.
fuente
CursorLoader
, asegúrese de llamarcursor.moveToPosition(-1)
antes de iterar, porque el cargador reutiliza el cursor cuando cambia la orientación de la pantalla. ¡Pasé una hora rastreando este problema!La mejor manera que he encontrado para pasar por un cursor es la siguiente:
No olvides cerrar el cursor después
EDITAR: La solución dada es excelente si alguna vez necesita iterar un cursor del que no es responsable. Un buen ejemplo sería, si está tomando un cursor como argumento en un método, y necesita escanear el cursor para un valor dado, sin tener que preocuparse por la posición actual del cursor.
fuente
Solo me gustaría señalar una tercera alternativa que también funciona si el cursor no está en la posición inicial:
fuente
moveToPosition(-1)
. Por lo tanto, ambas respuestas son igualmente consistentes, ya que ambas tienen dos llamadas de cursor. Creo que esta respuesta simplemente supera la respuesta de Borland, ya que no requiere el-1
número mágico.¿Qué tal usar foreach loop:
Sin embargo, mi versión de CursorUtils debería ser menos fea, pero cierra automáticamente el cursor:
fuente
Cursor
instancia en cada iteración del bucle.A continuación podría ser la mejor manera:
El código anterior aseguraría que pasaría por una iteración completa y no escaparía a la primera y última iteración.
fuente
Código de ejemplo:
fuente
iterator()
también debería volver a calcular eltoVisit = cursor.getCount();
usoclass IterableCursor<T extends Cursor> implements Iterable<T>, Iterator<T> {...
que recibe una clase queextends CursorWrapper implements MyInterface
MyInterface define getters para las propiedades de la base de datos. De esta manera tengo un Iterador basado en cursor <MiInterfaz>La solución Do / While es más elegante, pero si usa solo la solución While publicada anteriormente, sin moveToPosition (-1), perderá el primer elemento (al menos en la consulta de contacto).
Yo sugiero:
fuente
fuente
El cursor es la interfaz que representa una
2-dimensional
tabla de cualquier base de datos.Cuando intente recuperar algunos datos utilizando una
SELECT
instrucción, la base de datos primero creará un objeto CURSOR y le devolverá su referencia.El puntero de esta referencia devuelta apunta a la ubicación 0 que se llama como antes de la primera ubicación del cursor, por lo que cuando desea recuperar datos del cursor, debe mover primero al primer registro, así que tenemos que usar moveToFirst
Cuando invocas el
moveToFirst()
método en el cursor, lleva el puntero del cursor a la primera ubicación. Ahora puede acceder a los datos presentes en el primer registroLa mejor forma de mirar:
Cursor del cursor
fuente
Inicialmente cursor no está en la primera fila Mostrar el uso
moveToNext()
se puede repetir el cursor al registro no es existir, entoncesreturn false
, a menos quereturn true
,fuente