Android SQLite SQLiteOpenHelper IllegalStateException - DB уже закрыта ошибка

Это привело меня к сумасшествию в течение нескольких дней. У меня есть приложение для Android, которое довольно сложно. Он использует несколько потоков для извлечения данных с сервера и заполнения базы данных SQLite. Я использую singleton для ссылки на расширение SQLiteOpenHelper. Я открываю и закрываю базу данных в каждом из моих действий.

Ошибка ТОЛЬКО происходит в ситуации, когда я занимаюсь 4-мя действиями, а затем пытаюсь отступить. Я пробовал различные способы открытия и закрытия базы данных, включая перемещение close из onDestroy() к методам onPause(), а также добавление еще одного открытого в onResume().

Также обратите внимание, что мои действия сильно используют ListViews и ExpandableListViews, которые, как я понимаю, могут привести к закрытию базы данных на основе этой статьи: http://darutk-oboegaki.blogspot.com/2011/03/sqlitedatabase-is-closed-automatically.html p >

Я просмотрел код и убедился, что либо закрываю все свои курсоры, либо, если они назначаются адаптеру, вызывается startManagingCursor().

Кто-нибудь знает, что происходит?

java.lang.RuntimeException: Unable to resume activity {com.fieldone/com.fieldone.DispatchActivity}: java.lang.IllegalStateException: database /data/data/com.fieldone/databases/InterstateAirConditioning-1602814322.db already closed
    at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3347)
    at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:3362)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2162)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:144)
    at android.app.ActivityThread.main(ActivityThread.java:4937)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:521)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
    at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.IllegalStateException: database /data/data/com.fieldone/databases/InterstateAirConditioning-1602814322.db already closed
    at android.database.sqlite.SQLiteProgram.bindString(SQLiteProgram.java:237)
    at android.database.sqlite.SQLiteQuery.requery(SQLiteQuery.java:145)
    at android.database.sqlite.SQLiteCursor.requery(SQLiteCursor.java:567)
    at android.app.Activity.performRestart(Activity.java:3836)
    at android.app.Activity.performResume(Activity.java:3857)
    at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3337)
    ... 10 more

ОБНОВЛЕНИЕ: Я исправил проблему, но не уверен, ПОЧЕМУ это исправлено. Итак, может быть, кто-то там знает или может объяснить.

Когда я участвую в 4-й активности стека действий, я пытался закрыть db через db.close(). Независимо от того, где я это делаю, в onCreate после получения данных, которые мне нужны, или в onStop или onDestroy, это приведет к возникновению этой ошибки. Если я НЕ закрываю db, у меня нет проблемы. Итак, что-то заставляет db автоматически закрываться. Странная вещь, хотя я использую expandableListView в этом конечном действии, я НЕ использую cursorAdapter. У кого-нибудь есть мысли? Хотелось бы это понять.

Ответ 1

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

  • НЕ используйте управляемые курсоры. Есть причина, почему они устарели. Они совершенно проблематичны. Реально, существует очень мало сценариев, где вам действительно нужно использовать управляемый курсор в любом случае. Вместо этого запустите запрос и заполните объект результатами. Если вы запрашиваете несколько строк, создайте ArrayList < > вашего объекта, чтобы сохранить все строки. Теперь я создаю функцию, которая запускает запрос, и возвращает мне обратно ArrayList < > , а не курсор в возврате. Я закрываю курсор внутри функции, и я закончен. Для ListViews вы больше не сможете использовать SimpleCursorAdapter. Просто преобразуйте все их в BaseAdapter и используйте объект ArrayList < > , чтобы заполнить его.

  • НЕ ЗАБЫВАЙТЕ, ЧТОБЫ ЗАКРЫТЬ ВСЕ ВАШИ КУРСОРЫ. Это также может нанести ущерб вашим подключениям к приложениям db. Я думал, что делаю это, но, конечно же, нашел пятно, что я явно не закрывал курсор. Итак, зайдите в свое приложение и дважды проверьте все.

Я также использую singleton DatabaseHelper-объект. Я объявляю статический объект DatabaseHelper в классе SQLiteOpenHelper, чтобы каждый раз получать один и тот же экземпляр.

Теперь у меня есть стабильное приложение, которое больше не получает эти ошибки БД. Я надеюсь, что эта информация поможет некоторым из вас.

Ответ 2

использовать CursorAdapter.changeCursor(null), может замедлить появление этой ошибки, но не может полностью решить проблему, Неизвестный период времени снова появится. Это тоже сводило меня с ума!

Ответ 3

У меня также была та же проблема: "db уже закрытое исключение с недопустимым выражением курсора в fillWindow() и IllegalStatementException". Что я сделал, так это то, что я поместил свой курсор (w/c также из SimpleCursorAdapter) в переменную экземпляра вместо переменной метода, а затем в мои методы onStop и onPause я вызываю stopManagingCursor, а затем в мои методы onResume и onStart, которые я вызываю startManagingCursor.

Он решил мою проблему для меня, и после этого я не обнаружил никаких ошибок или предупреждающих сообщений в моем logcat:) Надеюсь, это тоже поможет.