Android: No se puede realizar esta operación porque se ha cerrado el grupo de conexiones

Estaba leyendo stackoverflow sobre esta pregunta y todavía no he encontrado una solución. Observo que a veces, mi aplicación lanza este error:

java.lang.IllegalStateException: Cannot perform this operation because the connection pool has been closed. at android.database.sqlite.SQLiteConnectionPool.throwIfClosedLocked(SQLiteConnectionPool.java:962) at android.database.sqlite.SQLiteConnectionPool.waitForConnection(SQLiteConnectionPool.java:599) at android.database.sqlite.SQLiteConnectionPool.acquireConnection(SQLiteConnectionPool.java:348) at android.database.sqlite.SQLiteSession.acquireConnection(SQLiteSession.java:894) ... 

Tengo un archivo llamado DatabaseHelper.java usando este método para obtener una instancia de él:

 public static DatabaseHelper getInstance(Context context) { if (mInstance == null) { mInstance = new DatabaseHelper(context.getApplicationContext()); } return mInstance; } 

Entonces tengo métodos como éste (que se estrelló en la línea cursor.moveToFirst () con ese error). Casi nunca se bloquea, pero a veces lo hace.

 public Profile getProfile(long id) { SQLiteDatabase db = this.getReadableDatabase(); String selectQuery = "SELECT * FROM " + TABLE_PROFILES + " WHERE " + KEY_PROFILES_ID + " = " + id; Cursor cursor = db.rawQuery(selectQuery, null); // looping through all rows and adding to list Profile profile = new Profile(); if (cursor.moveToFirst()) { doWhatEver(); } cursor.close(); db.close(); return profile; } 

Así que eso es todo, en todos los métodos que uso:

 SQLiteDatabase db = this.getReadableDatabase(); (or Writable) 

Y luego cierro el cursor y el db. En este caso, el error se lanzó en la línea:

 cursor.moveToFirst(); 

No veo por qué el error dice que el db está cerrado si estoy llamando this.getReadableDatabase () antes. ¡Por favor apoya! Gracias 🙂

retirar

 db.close(); 

Si intenta otra operación después de cerrar la base de datos, le dará esa excepción.

La documentación dice:

Libera una referencia al objeto, cerrando el objeto …

Además, echa un vistazo a la excepción de Android Sq Lite cerrada sobre un comentario de un ingeniero de Framework de Android que indica que no es necesario cerrar la conexión de base de datos.

Actualmente tengo el mismo problema. Al eliminar el db.close () resolver el problema para mí, creo que el problema es causado por multi-threading. Aquí están mis investigaciones.

SQLiteOpenHelper contiene una referencia a SQLiteDatabase, cuando getReadableDatabase () o getWritableDatabase () se llama, devolverá la referencia, si la SQLiteDatabase es cerrada o nula, se creará un nuevo objeto SQLiteDatabase. Tenga en cuenta que dentro del método get, los códigos se guardan en un bloque sincronizado.

SQLiteDatabase es una subclase de SQLiteClosable. SQLiteClosable implementa un esquema de conteo de referencia.

  • Cuando se crea por primera vez, el recuento es 1.

  • Cuando se ejecutan los métodos de operación de base de datos (como insertar, consulta), aumentará el recuento y disminuirá el recuento cuando finalicen los métodos. Sin embargo, las operaciones del cursor no están protegidas por el recuento de referencia.

  • Si el recuento disminuye a 0, el grupo de conexiones se cerrará y un objeto SQLiteConnectionPool miembro se establecerá en null y, a continuación, se cerrará SQLiteDatabase;

  • SQLiteDatabase.close () disminuirá el recuento en 1;

Por lo tanto, si tiene un esquema de subprocesamiento único, cerrar SQLiteDatabase estará bien porque SQLiteOpenHelper sólo volverá a crearlo.

Si hace multi-threading, entonces se encontrará con problemas. Digamos que el subproceso A y el subproceso B llaman getReadableDatabase () y SQLiteOpenHelper devuelve el SQLiteDatabase que contiene y, a continuación, el subproceso A terminó su operación y llama a SQLiteDatabase.close (), ahora el subproceso de objeto SQLiteDatabase B se ha cerrado para que cualquier operación db posterior Llamadas o método de método de cursor lanzará la excepción.

Estoy teniendo el mismo problema, no he sido capaz de solucionarlo. He encontrado una pista posible: Tengo un hilo de la sinc. Que esté funcionando todo el tiempo:

  Item ii = dbHelper.popPendingUpload(); if (ii != null) upload(ii); 

Y dentro de DBHelper

 public Item popPendingUpload() { SQLiteDatabase db = getReadableDatabase(); Cursor res = db .rawQuery("SELECT * FROM items WHERE state = 0 LIMIT 1", new String[] {}); boolean hasNext = res.moveToFirst(); Item ii = null; if (hasNext) { ii = //load item } db.close(); return ii; } 

El error también aparece en la llamada al método moveToFirst (). Como el hilo es poping elementos en un bucle infinito, la primera vez que funciona bien, la segunda vez que aparece el error. La parte interesante es que si pongo un punto de interrupción y paso a través del código, el error no muestra más. Estoy probando en un dispositivo real con Android 4.1.

Lo sé, no es una respuesta, pero puede ayudar. Voy a seguir probando.

 //close database after cursor is closed like: if(cursor.getCount() != 0){ while(cursor.moveToNext()){ //do operation } } cursor.close(); database.close(); 

Tal vez cierre la base de datos antes de acceder a la base de datos desde su aplicación.

Tienes que editar getProfile () para

 public Profile getProfile(long id) { SQLiteDatabase db = this.getReadableDatabase(); try { String selectQuery = "SELECT * FROM " + TABLE_PROFILES + " WHERE " + KEY_PROFILES_ID + " = " + id; Cursor cursor = db.rawQuery(selectQuery, null); // looping through all rows and adding to list Profile profile = new Profile(); if (cursor.moveToFirst()) { doWhatEver(); } cursor.close(); finally { db.close(); } return profile; } 

Tengo un error como el tuyo, aquí mi código:

  try { String sql = "SELECT * FROM "+DB_TABLEDOWNLOAD; Cursor cursor = db.rawQuery(sql, null); //空双引号为原表没有的字段String temp = ""; int existIconPath = cursor.getColumnIndex("iconPath"); int existAudioID = cursor.getColumnIndex("audioID"); if (existIconPath == -1 && existAudioID == -1){ temp = "url, downed,total,path,name, audioTitle, audioFileID,\"\",\"\""; }else if (existIconPath == -1 && existAudioID != -1){//iconPath不存在temp = "url, downed,total,path,name, audioTitle, audioFileID,\"\",audioID"; }else if (existIconPath != -1 && existAudioID == -1){//audioID不存在temp = "url, downed,total,path,name, audioTitle, audioFileID,iconPath,\"\""; }else { return; } db.beginTransaction(); String tempTableName = "_temp_"+DB_TABLEDOWNLOAD; String sqlCreateTemp = " ALTER TABLE "+DB_TABLEDOWNLOAD+" RENAME TO "+tempTableName+";"; db.execSQL(sqlCreateTemp); final String TB_TESTPAPERINFO_CREATE = "Create TABLE IF NOT EXISTS " + DB_TABLEDOWNLOAD + "(url TEXT, downed TEXT,total TEXT,path TEXT,name TEXT, audioTitle TEXT, audioFileID TEXT,iconPath TEXT, audioID TEXT);"; db.execSQL(TB_TESTPAPERINFO_CREATE); String sqlBackupData = "INSERT INTO "+DB_TABLEDOWNLOAD+" SELECT "+temp+" FROM "+tempTableName+";"; db.execSQL(sqlBackupData); String sqlDrop = "DROP TABLE IF EXISTS '"+tempTableName+"';"; db.execSQL(sqlDrop); db.setTransactionSuccessful(); } catch (Exception e) { e.printStackTrace(); }finally{ db.endTransaction(); } 
  • Android: ¿Cómo crear mi propia clase de cursor?
  • Compruebe si la consulta SQL ha tenido éxito en Android SQLite
  • Sugar ORM en Android: actualiza un objeto guardado en SQLite
  • Populating Spinner de la base de datos SQLite Android
  • Cómo y cuándo cerrar la base de datos sqlite en la aplicación con un montón de actividades y servicios
  • OrmLite SQLiteException: ninguna tabla
  • ¿Cuán cuidado debo tener con el hilo de seguridad al crear métodos / actividades que interactúan con la base de datos SQLite?
  • Cómo utilizar SQLiteDatabase.CursorFactory
  • SQLite onUpgrade ()
  • SQLite: Consulta que devuelve datos antiguos / en caché
  • La tabla de actualización utilizando el método rawQuery () no funciona
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.