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:
- Android Cursor? Cómo leer datos de objetos?
- INSERTAR O IGNORAR tabla con la clave AUTOINCREMENT en Android
- Obtener imagen Blob y convertir esa imagen en imagen de mapa de bits
- E / SQLiteLog (1893): (14) no puede abrir archivo en la línea 30176 de
- Sqlite Añadir columna en la tabla en una posición determinada (Android)
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 🙂
- Sqlite actualiza una columna basada en la cláusula where android
- ¿Es buena idea usar las preferencias compartidas de Android para almacenar grandes cantidades de datos?
- Cómo evitar errores de bloqueo de SQLiteException
- Android SQLiteOpenHelper no puede abrir el archivo de base de datos
- Insertar o actualizar en SQlite y Android utilizando la base de datos.query ();
- Android SQLite Rendimiento con índices
- SQLite, ¿cómo obtener todos los nombres de tablas en la base de datos?
- Búsqueda de Android: Utilice tablas de FTS junto con tablas normales de SQLite DB
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(); }
- Extraer el texto de la notificación de parcelable, contentView o contentIntent
- Reutilización de vistas en Android Listview con 2 diseños diferentes