Курсор Android - кажется, что moveToNext () не доходит до конца курсора

Почему мой курсор Android не доходит до конца исходного «обещания»??

Мой cursor.getCount() отличается от моего последнего cursor.getPosition(). Проверьте мой цикл while! Это все, что я делаю с ним!

Примечания: 1. речь идет о запросе поставщика содержимого контактов (android API> 5) 2. Я отображаю только основной код

Cursor cursor = mContext.getContentResolver().query(mUri, mProjections, null, null, null);
Logger.d(TAG, "***  cursor.getCount(): "+cursor.getCount());
while (cursor.moveToNext()) {
    Logger.d(TAG, "| position: "+cursor.getPosition());
    processMainCursor(serializer, cursor);
}
cursor.close();

processMainCursor() будет отображать данные из курсора + выполнять другие запросы: один 4 телефона, один 4 электронных письма, один 4 учетных записи IM:

void processMainCursor(XmlSerializer serializer, Cursor main_cursor) {
     writeCursorData(serializer, main_cursor); //writes cursor data, column by column
     writePhoneEntities(serializer, main_cursor);
     writeEmailEntities(serializer, main_cursor);
     writeIMEntities(serializer, main_cursor);
}

Ни в одном из моих writeXXX методов я не закрою свой main_cursor или не перейду к следующему!!! .. должен доверять мне в этом .. я просто делаю новый запрос, печатаю данные и закрываю этот курсор

Итак статистика:

  • cursor.getCount() = 695 (всегда)
  • комментирование writePhoneEntities, writeEmailEntities, writeIMEntities: cursor.getCount() = last cursor.getPosition() = 695 (так правильно!)
  • оставление одного/двух/всех моих writeXEntities показывает случайность; пример: оставить их все: last cursor.getPosition() иногда отображает 254, 257, 253 и т. д.; оставляя только телефон и IM: 514, 510, 511 и т. д. (такие разные RUN -> разные last cursor.getPosition() VALUE)

Итак, мнения.. Почему так? Это связано с памятью?

Обновление: оставлено любое из моих отображений writeXEntities в конце logcat: Удаление мертвого поставщика контента: контакты

Обновление 2 Добавление cursor.moveToFirst(); и повторение цикла

do {
    //do whatever you want
} while (cursor.moveToNext()); 

работу не выполнил..

Так что, возможно, ответ находится в этих записях logcat:

05-21 23:29:30.209: I/ActivityThread(7085): Removing dead content provider: contacts
05-21 23:29:30.209: I/ActivityThread(7085): Removing dead content provider: com.android.contacts

ОБРАЗЕЦ writeXEntity УДАЛЕН

РЕШЕНИЕ .. я не правильно закрывал курсоры из writeXEntity (вероятно, оставляя довольно много открытых курсоров после основного времени)

на самом деле я так закрывался

if(phone_cursor!=null && phone_cursor.getCount() > 0)
{                   
     //... stuff
     phone_cursor.close();
}

я должен был закрыться после if

if(phone_cursor!=null && phone_cursor.getCount() > 0)
{                   
     //... stuff
}
phone_cursor.close();

Я думаю, оставить курсор basilion открытым .. был ответ?!?


person pulancheck1988    schedule 03.06.2012    source источник
comment
Пожалуйста, опубликуйте одну (или все) из ваших write функций, то, что вы опубликовали, должно работать нормально.   -  person Sam    schedule 03.06.2012
comment
Вы должны опубликовать свое решение в качестве ответа, а затем принять его, чтобы все знали, что решение было найдено (без необходимости открывать сообщение и читать его).   -  person Barak    schedule 08.06.2012


Ответы (4)


Вам нужно переместить курсор на первую строку. Попробуйте добавить cur.moveToFirst() перед циклом while.

Вы также можете рассмотреть возможность использования цикла do-while. Это гарантирует, что вы никогда не пропустите первую строку в курсоре:

if (cursor.moveToFirst()) {
    do {
        //do whatever you want
    } while (cursor.moveToNext());               
}
cursor.close();
person Alex Lockwood    schedule 03.06.2012
comment
По примеру автора: он вызывает курсор, печатает оператор и использует cursor.moveToNext(). Новый курсор установлен на индекс: -1 и moveToNext() переместят индекс на 0, поэтому (если это все, что делает pulancheck) moveToFirst() не нужен, так как moveToNext() уже перемещает индекс в первую строку. - person Sam; 03.06.2012
comment
да, Сэм, но почему код печатает разные cursor.getPosition() .. в разных RUN?? (это происходит, когда у меня все/некоторые из моих writeXEntity раскомментированы) и как насчет моего последнего сообщения logCat Удаление мертвого поставщика контента - person pulancheck1988; 03.06.2012
comment
@pulancheck1988 Мой комментарий здесь является ответом на ответ Алекса, с которым я не согласен, учитывая контекст. Я понятия не имею, почему ваш индекс меняется, см. мой комментарий к вашему вопросу, в котором запрашивается дополнительный код. - person Sam; 03.06.2012

Ну, они не будут одинаковыми, так как getCount — это количество элементов, а position — это позиция (первое значение равно 0). Таким образом, конечная позиция всегда должна быть на единицу меньше, чем количество.

Если это что-то другое, я думаю, я не понимаю ваш вопрос должным образом.

person Barak    schedule 03.06.2012

Используйте курсор, как показано ниже:

             if(cursor.getCount() == 0)
              {                   
                 //No entry found
              }
              else  {
                  cursor.moveToFirst();
                  do {
                     //do whatever you want
                     } while (cursor.moveToNext());               
            cursor.close();
person Imran Rana    schedule 03.06.2012
comment
я изменил все свои циклы курсора, как вы сказали, и результат: первый RUN - последняя позиция курсора: 257, второй RUN: 256 ... так что все еще не достиг обещанного 695. - person pulancheck1988; 03.06.2012

После прочтения ответа, который вы уже нашли (проблема с закрывающими курсорами), я думаю, что лучший способ убедиться, что вы закрываете их все, - это использовать этот код:

Cursor c = null;
try {
   c = <your query>;
   if (c.moveToFirst()) { // No point in doing more if empty.
      do {
         <process this cursor row>
      } while (c.moveToNext());
   }
}
finally {
   if (c != null) c.close(); // Not sure the check needed, maybe if query was really wrong.
}
person Asincrono    schedule 30.07.2013