10

Esto me ha estado volviendo loco por unos días. Tengo una aplicación de Android que es bastante compleja. Utiliza varios subprocesos para extraer datos de un servidor y completar 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.Android SQLite SQLiteOpenHelper IllegalStateException - DB ya error cerrado

El error SÓLO ocurre en una situación en la que estoy a 4 actividades de profundidad y luego intento dar marcha atrás. He intentado varias formas de abrir y cerrar la base de datos, incluido mover el cierre de los métodos onDestroy() a onPause() y también agregar otro abierto al onResume().

También hay que resaltar, mis actividades hacen un uso intensivo de listviews y ExpandableListViews, que entiendo que podría causar la base de datos para cerrar la base de este artículo: http://darutk-oboegaki.blogspot.com/2011/03/sqlitedatabase-is-closed-automatically.html

He pasado por el código y se aseguró de que soy cerrando todos mis cursores o, si están asignados a un adaptador, llamando 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 está seguro de por qué esto lo arregló. Entonces, tal vez alguien por ahí sabe o podría explicar.

Cuando estoy en la 4ta actividad de la pila de actividades, estaba intentando cerrar el db a través de db.close(). No importa dónde coloque 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 estoy teniendo el problema. Entonces, algo está causando que el db se cierre automáticamente. Lo extraño es que, aunque estoy usando un expandListView en esta actividad final, NO estoy usando un cursorAdapter. Alguien tiene alguna idea? Me encantaría entender esto.

Respuesta

19

Dado que esta cuestión ha recibido una gran atención, quería responder a ella y describir lo que he aprendido y lo que funcionó para mí para corregir este problema en mi solicitud grande, con bases de datos:

  1. NO utilice cursores administrados. Hay una razón por la que están en desuso. Son completamente problemáticos. Siendo realistas, hay muy pocos escenarios en los que realmente necesite utilizar un cursor administrado de todos modos. En su lugar, ejecute su consulta y llene un objeto con los resultados. Si está consultando una fila múltiple, cree una ArrayList <> de su objeto para contener todas las filas. Lo que hago ahora es crear una función que ejecute la consulta y me devuelva mi ArrayList <> en lugar de un cursor en la declaración. Cierro el cursor dentro de la función y termino. Para un ListViews, ya no podrá usar un SimpleCursorAdapter. Simplemente conviértelos a un BaseAdapter y use su objeto ArrayList <> para rellenarlo.

  2. NO OLVIDES CERRAR TODOS TUS CURSORES. Esto también puede causar estragos en las conexiones de db de su aplicación. Pensé que estaba haciendo esto pero, por supuesto, encontré un punto en el que no estaba cerrando el cursor explícitamente. Por lo tanto, revise su aplicación y vuelva a verificarlos todos.

También estoy usando un objeto DatabaseHelper único.Declaro un objeto DatabaseHelper estático dentro de mi clase SQLiteOpenHelper para que obtenga la misma instancia cada vez.

Ahora tengo una aplicación de ejecución estable que ya no recibe estos errores de base de datos. Espero que esta información sea útil para algunos de ustedes.

2

use CursorAdapter.changeCursor (null), puede ralentizar la aparición de este error, pero no puede resolver completamente el problema, aparecerá un período de tiempo desconocido. ¡Esto también me está volviendo loco!

1

También tuve el mismo problema 'db ya cerró la excepción con una instrucción inválida de cursor en fillWindow() y IllegalStatementException'. Lo que hice fue poner mi cursor (w/c también viene de SimpleCursorAdapter) en una variable de instancia en lugar de una variable de método, luego en mis métodos onStop y onPause llamo stopManagingCursor y luego en mis métodos onResume y onStart llamo startManagingCursor.

Resolvió mi problema y no encontré ningún mensaje de error o advertencia en mi logcat después de eso :) Espero que esto ayude a cualquiera también.

Cuestiones relacionadas