Я часто вижу код, который включает в себя итерацию по результату запроса к базе данных, выполнение чего-либо с каждой строкой, а затем переход к следующей строке. Типичные примеры следующие.
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());
}
Все это кажется мне чрезмерно скучным, каждый из которых имеет несколько вызовов Cursor
методов. Конечно, должен быть аккуратный путь?
Ответы:
Самый простой способ это:
Курсор начинается перед первой строкой результата, поэтому на первой итерации он перемещается к первому результату, если он существует . Если курсор пуст или последняя строка уже обработана, цикл завершается аккуратно.
Конечно, не забудьте закрыть курсор, как только закончите, желательно в
finally
предложении.Если вы нацелены на API 19+, вы можете использовать try-with-resources.
источник
CursorLoader
, убедитесь, что вы вызываетеcursor.moveToPosition(-1)
перед итерацией, потому что загрузчик повторно использует курсор при изменении ориентации экрана. Потратил час на поиск этой проблемы!Самый лучший способ прохождения курсора - это следующее:
Не забудьте потом закрыть курсор
РЕДАКТИРОВАТЬ: Данное решение отлично подходит, если вам когда-либо нужно перебрать курсор, за который вы не несете ответственности. Хорошим примером будет, если вы берете курсор в качестве аргумента в методе, и вам нужно сканировать курсор на предмет заданного значения, не беспокоясь о текущей позиции курсора.
источник
Я просто хотел бы указать на третий вариант, который также работает, если курсор не находится в начальной позиции:
источник
moveToPosition(-1)
. Таким образом, оба ответа в равной степени состоят в том, что оба имеют два вызова курсора. Я думаю, что этот ответ только обрезает ответ Борланда, так как не требует-1
магического числа.Как насчет использования цикла foreach:
Однако моя версия CursorUtils должна быть менее уродливой, но она автоматически закрывает курсор:
источник
Cursor
экземпляр в каждой итерации цикла.Ниже может быть лучший способ:
Приведенный выше код гарантирует, что он пройдет всю итерацию и не избежит первой и последней итерации.
источник
Пример кода:
источник
iterator()
следует также пересчитатьtoVisit = cursor.getCount();
Я использую,class IterableCursor<T extends Cursor> implements Iterable<T>, Iterator<T> {...
который получает класс,extends CursorWrapper implements MyInterface
где MyInterface определяет геттеры для свойств базы данных. Таким образом, у меня есть итератор на основе курсора <MyInterface>Решение Do / While более элегантно, но если вы используете только решение While, опубликованное выше, без moveToPosition (-1) вы пропустите первый элемент (по крайней мере, в запросе Contact).
Я предлагаю:
источник
источник
Курсор является интерфейс , который представляет собой
2-dimensional
таблицу в любой базе данных.Когда вы пытаетесь получить некоторые данные с помощью
SELECT
оператора, база данных сначала создаст объект CURSOR и вернет вам его ссылку.Указатель этой возвращенной ссылки указывает на 0-е местоположение которая в противном случае вызывается так же, как и до первой позиции Курсора, поэтому, когда вы хотите извлечь данные из курсора, вам нужно сначала перейти к первой записи, поэтому мы должны использовать moveToFirst
Когда вы вызываете
moveToFirst()
метод для курсора, он переводит указатель курсора в 1-е место. Теперь вы можете получить доступ к данным, присутствующим в 1-й записиЛучший способ выглядеть:
Курсор Курсор
источник
Первоначально курсор находится не в первой строке показа, с помощью которого
moveToNext()
вы можете выполнить итерацию курсора, когда запись не существует, затемreturn false
, если она не существуетreturn true
,источник