Frequentemente, vejo o código que envolve a iteração sobre o resultado de uma consulta ao banco de dados, fazendo algo com cada linha e passando para a próxima linha. Exemplos típicos são os seguintes.
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());
}
Tudo isso me parece excessivamente longo, cada um com várias chamadas para Cursor
métodos. Certamente deve haver uma maneira mais limpa?
Respostas:
A maneira mais simples é esta:
O cursor inicia antes da primeira linha do resultado, portanto, na primeira iteração, ele se move para o primeiro resultado, se existir . Se o cursor estiver vazio ou a última linha já tiver sido processada, o loop será encerrado ordenadamente.
Obviamente, não se esqueça de fechar o cursor quando terminar, de preferência em uma
finally
cláusula.Se você segmentar a API 19+, poderá usar a tentativa com recursos.
fonte
CursorLoader
, certifique-se de ligarcursor.moveToPosition(-1)
antes da iteração, porque o carregador reutiliza o cursor quando a orientação da tela muda. Passou uma hora rastreando esse problema!A maneira mais bonita que encontrei para percorrer um cursor é a seguinte:
Não esqueça de fechar o cursor depois
EDIT: A solução fornecida é ótima se você precisar iterar um cursor do qual você não é responsável. Um bom exemplo seria se você estiver usando um cursor como argumento em um método e precisar varrer o cursor em busca de um determinado valor, sem precisar se preocupar com a posição atual do cursor.
fonte
Gostaria apenas de apontar uma terceira alternativa que também funciona se o cursor não estiver na posição inicial:
fonte
moveToPosition(-1)
. Portanto, ambas as respostas são igualmente consistentes, pois ambas têm duas chamadas de cursor. Eu acho que essa resposta apenas delineia a resposta de Borland, pois não requer o-1
número mágico.Que tal usar o loop foreach:
No entanto, minha versão do CursorUtils deve ser menos feia, mas fecha automaticamente o cursor:
fonte
Cursor
instância em cada iteração do loop.Abaixo pode ser a melhor maneira:
O código acima garantiria que passaria por toda a iteração e não escaparia da primeira e da última iteração.
fonte
Código de exemplo:
fonte
iterator()
também deve recalcular otoVisit = cursor.getCount();
usoclass IterableCursor<T extends Cursor> implements Iterable<T>, Iterator<T> {...
que recebe uma classe em queextends CursorWrapper implements MyInterface
MyInterface define getters para propriedades do banco de dados. Desta forma, eu tenho um cursor com base Iterator <MyInterface>A solução Do / While é mais elegante, mas se você usar apenas a solução While postada acima, sem a moveToPosition (-1), você perderá o primeiro elemento (pelo menos na consulta de contato).
Eu sugiro:
fonte
fonte
O cursor é a interface que representa um
2-dimensional
tabela de qualquer banco de dados.Quando você tenta recuperar alguns dados usando a
SELECT
instrução, o banco de dados cria primeiro um objeto CURSOR e retorna sua referência a você.O ponteiro desta referência retornada está apontando para o 0º local que, de outra forma, é chamado como antes do primeiro local do Cursor. Portanto, quando você deseja recuperar dados do cursor, deve primeiro mover-se para o 1º registro, para que possamos usar moveToFirst
Quando você invoca o
moveToFirst()
método no Cursor, ele leva o ponteiro do cursor para o 1º local. Agora você pode acessar os dados presentes no 1º registroA melhor maneira de olhar:
Cursor do cursor
fonte
Inicialmente, o cursor não está no primeiro show de linha usando.
moveToNext()
Você pode iterar o cursor quando o registro não existirreturn false
, a menos quereturn true
,fonte