Завершение курсора, который не был деактивирован или закрыт нефатальной ошибкой - PullRequest
33 голосов
/ 18 июня 2010

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

Так как это нефатальная ошибка, сбоя не происходит, и все, кажется, работает хорошо .. но мне не нравится ошибка.

Если я закрою курсор в конце этого кода .. список остается пустой. если я закрываю курсор в 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) 
.... 
.... 

Ответы [ 9 ]

27 голосов
/ 18 июня 2010

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

13 голосов
/ 09 сентября 2010

Скотт,

Я столкнулся с той же проблемой, что и вы.Перед закрытием базы данных, то есть 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's close the cursor.
    mCursor.close();
    db.close(); 
} 

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

2 голосов
/ 19 февраля 2011

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

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

1 голос
/ 28 декабря 2012

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

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

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

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

1 голос
/ 30 сентября 2012

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

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

0 голосов
/ 02 февраля 2012

startManagingCursor (курсор);

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

0 голосов
/ 01 декабря 2011

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

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

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

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

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

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

  • Кажется работающим сделать задачу внутренним классом действия и закрыть курсор в методе onStop действия.

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

0 голосов
/ 02 ноября 2011

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

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

0 голосов
/ 11 декабря 2010

Я боролся с этой проблемой в течение двух дней.Я пытался заставить работать пример кода, который передавал курсор, возвращенный из запроса к базе данных, прямо в List Adapter - без промежуточного адаптера.Он отказывался работать - просто отображал пустой экран - пока я не вызвал «moveToFirst ()» для курсора, прежде чем передать его в ListAdapter.Пойди разберись!Когда я это комментирую, это ломается.

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

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

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