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

Исключение: попытка получить ссылку на закрытие SQLiteClosable

Я отправил этот еще в мае в группу разработчиков Google [android-developers]. Я никогда не слышал назад и не смог воспроизвести проблему, пока один из моих учеников не сделал на прошлой неделе. Я подумал, что я разместил его здесь и посмотрю, звонит ли он кому-нибудь из колокольчиков.

В одном из моих образцов кода у меня есть следующий метод:

static Cursor getAll(SQLiteDatabase db, String orderBy) {
        return(db.rawQuery("SELECT * FROM restaurants "+orderBy, null));

}

Когда я запускаю его, спорадически, я получаю следующее:

05-01 14:45:05.849: ERROR/AndroidRuntime(1145):
java.lang.IllegalStateException: attempt to acquire a reference on a
close SQLiteClosable
05-01 14:45:05.849: ERROR/AndroidRuntime(1145):     at
android.database.sqlite.SQLiteClosable.acquireReference(SQLiteClosable.java:31)
05-01 14:45:05.849: ERROR/AndroidRuntime(1145):     at
android.database.sqlite.SQLiteProgram.<init>(SQLiteProgram.java:56)
05-01 14:45:05.849: ERROR/AndroidRuntime(1145):     at
android.database.sqlite.SQLiteQuery.<init>(SQLiteQuery.java:49)
05-01 14:45:05.849: ERROR/AndroidRuntime(1145):     at
android.database.sqlite.SQLiteDirectCursorDriver.query(SQLiteDirectCursorDriver.java:49)
05-01 14:45:05.849: ERROR/AndroidRuntime(1145):     at
android.database.sqlite.SQLiteDatabase.rawQueryWithFactory(SQLiteDatabase.java:1118)
05-01 14:45:05.849: ERROR/AndroidRuntime(1145):     at
android.database.sqlite.SQLiteDatabase.rawQuery(SQLiteDatabase.java:1092)
05-01 14:45:05.849: ERROR/AndroidRuntime(1145):     at
apt.tutorial.Restaurant.getAll(Restaurant.java:14)

Это не имеет никакого смысла для меня. База данных определенно открыта. SQLiteClosable - это SQLiteQuery, созданный SQLiteQueryDriver, и я не вижу доказательств того, что есть пул объектов или что-то происходит здесь что может объяснить, как "новый" SQLiteClosable уже закрыт. факт, что он спорадический (что означает, что иногда выполняются одни и те же операции пользовательского интерфейса инициировать исключение, но не всегда) предлагает какой-то пул, расы состояние или что-то... но я не знаю, где.

Мысли?

Спасибо!

ОБНОВЛЕНИЕ. Этот код относится к учебникам LunchList из моей книги Android Programming Tutorials. Он немного разложен и не очень подходит для публикации непосредственно в SO. Вы можете загрузить код для этой книги из приведенной выше ссылки, если хотите взглянуть на нее. Я не помню точно, какой выпуск учебника, над которым работал студент в то время, хотя он был в Tutorial 12-Tutorial 16. Я в основном надеялся столкнуться с тем, кто раньше споткнул об этой проблеме и имел вероятного виновника. Я уверен, что моя база данных открыта. Еще раз спасибо!

4b9b3361

Ответ 1

Это заставило меня сумасшедшим в течение самого долгого времени. Решение, которое я нашел, довольно просто: не сохраняйте ссылки на объекты SQLiteDatabase. Вместо этого используйте SQLiteOpenHelper и вызывайте getWritableDatabase() каждый раз, когда вам это нужно. Из документов:

общедоступная синхронизированная SQLiteDatabase getWritableDatabase()

Создайте и/или откройте базу данных, которая будет использоваться для чтения и записи. После успешного открытия база данных кэшируется, поэтому вы можете вызывать этот метод каждый раз, когда вам нужно писать в базу данных.

Ответ был там все время.

Ответ 2

SQLiteDatabase автоматически закрывается при некоторых условиях.

http://darutk-oboegaki.blogspot.com/2011/03/sqlitedatabase-is-closed-automatically.html

getCount() и onMove() методы курсора запускают фактический запрос с использованием SQLiteQuery. После получения всех необходимых данных SQLiteQuery уменьшает счетчик ссылок экземпляра SQLiteDatabase. Когда счетчик ссылок достигает 0, база данных закрывается.

Обратите внимание, что запрос может выполняться асинхронно, и в таком случае getCount() может возвращать -1, если он вызывается до того, как SQLiteQuery завершит подготовку данных.

Ответ 3

У меня была такая же проблема в течение нескольких дней, и моим решением было поместить метод open() непосредственно перед моим методом query и close() после операции с базой данных. Это выглядит примерно так.

open();
Cursor cur=db.query(DATABASE_TABLE_CON, null, null, null, null, null, " name ASC");
close();
return cur;

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

Ответ 4

У меня возникла аналогичная проблема, несмотря на то, что уже после совет Jarett. В моем случае проблема происходит довольно регулярно при изменении ориентации. Я обнаружил, что по какой-то причине я еще не дошел до конца, мой код генерирует две идентичные, довольно одновременные AsyncTasks при изменении ориентации (в отличие от только одного, когда активность начинается нормально). Эти задачи одновременно выполняют один и тот же запрос базы данных из разных потоков.

Это исключение (или иногда некоторое другое SQLiteException) является результатом. Таким образом, кажется, что это сообщение может быть симптомом проблем concurrency, даже если это не обязательно корень исходной проблемы, размещенной здесь.