SQLite SQLiteOpenHelper IllegalStateException – Error de DB ya cerrado
Esto me ha vuelto loco desde hace unos días. Tengo una aplicación de Android que es bastante complejo. Utiliza varios subprocesos para extraer datos de un servidor y rellenar la base de datos SQLite. Estoy usando un singleton para hacer referencia a mi extensión de SQLiteOpenHelper. Estoy abriendo y cerrando la base de datos en cada una de mis actividades.
El error sólo ocurre en una situación en la que estoy 4 actividades de profundidad y luego tratar de retroceder. He intentado varias formas de abrir y cerrar la base de datos, incluyendo mover el cierre de los métodos onDestroy () a onPause () y también agregar otro abierto a onResume ().
- Consulta de suma en sqlite en android
- Idioma para cerrar un cursor
- Android: ¿puedo usar una clase SQLiteOpenHelper para varios archivos de base de datos?
- SQLite por qué copiamos db en carpeta de activos
- ¿Los campos de datos SQLite null ocupan más memoria?
También de la nota, mis actividades hacen el uso pesado de ListViews y de ExpandableListViews, que entiendo podría causar la base de datos para cerrar sobre la base de este artículo: http://darutk-oboegaki.blogspot.com/2011/03/sqlitedatabase-is-closed- Automáticamente.html
He revisado el código y me aseguro de cerrar cualquiera de mis cursores o, si están siendo asignados a un adaptador, llamar a startManagingCursor ().
¿Alguien tiene una idea de lo que está pasando?
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
ACTUALIZACIÓN: He arreglado el problema, pero no estoy seguro de por qué esto lo arregló. Por lo tanto, tal vez alguien por ahí sabe o podría explicar.
Cuando estoy en la cuarta actividad de la pila de actividades, estaba tratando de cerrar el db a través de db.close (). No importa dónde he puesto esto, en el onCreate después de obtener los datos que necesito, o en el onStop o onDestroy, se producirá este error. Si NO cierro el db, no voy a tener el problema. Por lo tanto, algo está causando el db para cerrar automáticamente. Lo extraño es que, aunque estoy utilizando un expandibleListView en esta actividad final, NO estoy usando un cursorAdapter. Alguien tiene alguna idea? Me encantaría entender esto.
- Cómo obtener el valor de la base de datos en una matriz String en android (sqlite Database)
- Android: múltiples subprocesos que escriben en la base de datos SQLite
- ¿Cómo usar SQLiteOpenHelper con la base de datos en sd-card?
- Problema con SQL Query Android Where Clause
- ¿Es posible comparar dos cursores?
- ¿Es posible perder una conexión de base de datos SQLite?
- Encriptación de contraseña de Android SQlite?
- Uso correcto de Sqlite en Android (SQLiteOpenHelper, conexiones, hilo principal, etc ...)
Dado que esta pregunta ha recibido mucha atención, quería responder y describir lo que he aprendido y lo que funcionó para mí para corregir este problema en mi gran aplicación basada en bases de datos:
-
NO utilice cursores administrados. Hay una razón por la que están obsoletos. Son completamente problemáticos. Realista, hay muy pocos escenarios en los que realmente necesita utilizar un cursor administrado de todos modos. En su lugar, ejecute su consulta y rellenar un objeto con los resultados. Si está consultando varias filas, cree una ArrayList <> de su objeto para mantener todas las filas. Lo que hago ahora es crear una función que ejecute la consulta y me devuelve mi ArrayList <> en lugar de un cursor en la devolución. Cierro el cursor dentro de la función y he terminado. Para un ListViews, ya no podrá utilizar un SimpleCursorAdapter. Basta con convertir todos estos a un BaseAdapter y utilizar su ArrayList <> objeto para llenarlo.
-
NO OLVIDE CERRAR TODOS SUS CURSORES. Esto también puede causar estragos en las conexiones db de su aplicación. Pensé que estaba haciendo esto, pero, claro, encontré un lugar que no estaba cerrando explícitamente un cursor. Por lo tanto, ir a través de su aplicación y comprobar todos ellos.
También utilizo un objeto singleton DatabaseHelper. Declaro un objeto estático de DatabaseHelper dentro de mi clase de SQLiteOpenHelper de modo que consiga la misma instancia cada vez.
Ahora tengo una aplicación en ejecución estable que ya no recibe estos errores de DB. Espero que esta información sea útil para algunos de ustedes.
Utilice CursorAdapter.changeCursor (null), puede retardar la aparición de este error, pero no puede resolver completamente el problom, periodo de tiempo desconocido aparecerá de nuevo. ¡Esto también me ha vuelto loco!
También tuve el mismo problema 'db ya cerrado excepción con un cursor inválido en la declaración fillWindow () y IllegalStatementException'. Lo que hice fue poner mi cursor (w / c también viene de SimpleCursorAdapter) a una variable de instancia en lugar de una variable de método, a continuación, en mi onStop y onPause métodos llamo stopManagingCursor, a continuación, en mi onResume y métodos onStart que llamo startManagingCursor.
Resolvió mi problema para mí y no encontré ningún mensaje de error o de advertencia en mi logcat después de eso 🙂 Espero que esto ayude a cualquiera también.
- Dependencias de Gradle con Travis CI en proyecto Android
- Android: Limitar el texto de edición a números