Подтвердить что ты не робот

Завершение курсора, который не был деактивирован или закрыт нефатальной ошибкой

Я получаю "Завершение курсора, который не был деактивирован или закрытой "ошибкой на этом фрагменте кода. Код используется для заполнения списка.

Поскольку это нефатальная ошибка, нет сбоя, и все, кажется, работает отлично.. но мне не нравится ошибка.

Если я закрою курсор в конце этого кода. пустой. если я закрою курсор в onStop, я получаю ту же ошибку.

Как это исправить?

private void updateList() { 
        DBAdapter db = new DBAdapter(this); 
        db.open(); 
            //load all waiting alarm 
            mCursor=db.getTitles("state<2"); 
            setListAdapter(new MyCursorAdapter(this, mCursor)); 
            registerForContextMenu(getListView()); 
            db.close(); 
        } 


error : 


E/Cursor  ( 2318): Finalizing a Cursor that has not been deactivated 
or closed. database = /data/data/xxxxxxxxxxxxxxx.db, table = alerts, 
query = SELECT _id, alert_id, 
E/Cursor  ( 2318): 
android.database.sqlite.DatabaseObjectNotClosedException: Application 
did not close the cursor or database 
object that was opened here 
E/Cursor  ( 2318):      at 
android.database.sqlite.SQLiteCursor.<init>(SQLiteCursor.java:210) 
E/Cursor  ( 2318):      at 
android.database.sqlite.SQLiteDirectCursorDriver.query(SQLiteDirectCursorDr­iver.java: 
53) 
E/Cursor  ( 2318):      at 
android.database.sqlite.SQLiteDatabase.rawQueryWithFactory(SQLiteDatabase.j­ava: 
1345) 
E/Cursor  ( 2318):      at 
android.database.sqlite.SQLiteDatabase.queryWithFactory(SQLiteDatabase.java­: 
1229) 
.... 
.... 
4b9b3361

Ответ 1

Вы не должны получать это сообщение, если закрываете Cursor в onStop() или onDestroy(). Повторите попытку. Или вызовите startManagingCursor() после получения Cursor из вашего запроса, и Android закроет Cursor самостоятельно.

Ответ 2

Скотт,

Я столкнулся с той же проблемой, что и вы. Прежде чем закрыть базу данных, т.е. "Db.close()," убедитесь, что ваши курсоры закрыты первыми, то есть "mCursor.close()"

Так же:

private void updateList()
{ 
    DBAdapter db = new DBAdapter(this);
    db.open();

    //load all waiting alarm
    mCursor=db.getTitles("state<2"); 
    setListAdapter(new MyCursorAdapter(this, mCursor)); 
    registerForContextMenu(getListView()); 

    // Let close the cursor.
    mCursor.close();
    db.close(); 
} 

Вы упомянули, что если вы закрыли курсор, ваш список останется пустым. Я рекомендую передать информацию в класс и скопировать ее (выделить память), затем закрыть курсор.

Ответ 3

Когда запрос возвращает курсор, он фактически позиционируется "до" первого запись в курсор. Адаптер попытается выполнить "getItem" на первом , поэтому он будет терпеть неудачу, поскольку курсор не расположен ни на одном.

В моих базовых адаптерах я делаю курсорMoveToPosition на getViews. Это кажется для устранения необходимости перехода вперед.

Ответ 4

Не используйте startManagingCursor(), поскольку это уже не рекомендуемый подход. Проблема возникает из-за того, что соединение курсора/БД все еще не закрывается к тому времени, когда финализатор доберется до этого объекта. Вы можете избежать этого, либо позволяя загрузчику управлять курсором, либо самостоятельно отслеживать все соединения курсора /DB/SQLiteOpenHelper и очищать их после.

Использование Loader довольно громоздко и требует много движущихся частей для его работы в сочетании с утверждением списка. С другой стороны, отслеживание ваших курсоров и соединений с базой данных подвержено человеческой ошибке. Если количество объектов курсора/БД низкое, я бы рекомендовал последнее решение. Если нет, позвольте загрузчику обрабатывать ваши соединения.

Ответ 5

Закройте объект курсора, где бы вы его не создавали.

Когда вы создаете объект курсора и выполняете его с помощью таблицы SQLite, закройте его после его использования. Это закрытие курсора предотвращает исключение в logcat.

У вас не будет никаких исключений, связанных с завершением открытия курсора.

Эта фиксированная проблема в моем приложении.

Ответ 6

Я боролся с этой проблемой в течение двух дней. Я пытался получить образец кода, который передавал курсор, возвращаемый из запроса базы данных, непосредственно в Адаптер списка - без промежуточного адаптера. Он отказался работать - просто отобразил пустой экран - пока я не вывел 'moveToFirst()' на курсор, прежде чем передавать его в ListAdapter. Иди цифра! Когда я прокомментирую это, он ломается.

Просто подумал, что я поделюсь этим, чтобы спасти людей той же борьбой, что и я.

Если кто-то может пролить свет на то, почему это так, я был бы признателен. Мне не приходилось ссылаться на moveToFirst на курсоры до сих пор, чтобы заставить их нормально работать.

Ответ 7

У меня была такая же проблема, и я подумал, чтобы вы знали - на всякий случай....

Я случайно вызвал свою процедуру выборки два раза и, таким образом, "потерял" полученный курсор первого вызова. Это вызвало ошибку.

Ответ 8

У меня тоже были проблемы с закрытием курсора:

  • Закрытие курсора сразу после установки адаптера просмотра списка заставляет курсор закрываться до отображения данных.

  • Нельзя использовать startManagingCursor для управления курсором, потому что он устарел.

  • Новая замена cursorLoader для startManagingCursor кажется излишней.

  • Перемещение позиции курсора, как было предложено, не работает.

  • Сделать задачу внутренним классом активности и закрывать курсор в действии метод onDestroy работает иногда, но не все время.

  • Выполнение задачи является внутренним классом активности и закрытием курсора в методе onStop.

Я также узнал, что я могу закрыть базу данных и открыть помощник sqlite перед закрытием курсора. Я могу даже закрыть их сразу после установки адаптера просмотра списка. Данные будут отображаться.

Ответ 9

startManagingCursor (курсор);

Это устранило мою проблему