2012-10-09 21 views
19

I que tiene un problema con el controlador de SQLAndroid SQLite filtró

A SQLiteConnection object for database '/data/data/.../databases/queueManager' was leaked! Please fix your application to end transactions in progress properly and to close the database when it is no longer needed. 

tomado de Androidhive tutorial y personalizado para mi uso

la mesa parece

+ ----------------------------------------------------------- + 
: DATABASE_ID : DATABASE_QID : DATABASE_QUEUE : DATABASE_DATE : 
+ ----------------------------------------------------------- + 

El código

DBQueue searchDBqid(int id) { 
     SQLiteDatabase db = this.getReadableDatabase(); 

     String selectQuery = "SELECT * FROM " + TABLE_QUEUE + " WHERE " + DATABASE_QID + " = " + id; 

      Cursor cursornum = db.rawQuery(selectQuery, null); 
      int dk = cursornum.getCount(); 
      cursornum.close(); 

      if (dk >0) { 
       Cursor cursor = db.query(TABLE_QUEUE, new String[] { DATABASE_ID, 
         DATABASE_QID, DATABASE_QUEUE, DATABASE_DATE }, DATABASE_QID + "=?", 
         new String[] { String.valueOf(id) }, null, null, null, null); 

       if (cursor != null) cursor.moveToFirst(); 

       DBQueue dbqueue = new DBQueue(Integer.parseInt(cursor.getString(0)), 
         cursor.getString(1), cursor.getString(2), cursor.getString(3)); 
       return dbqueue; 
      } 

     db.close(); 
     return null; 
    } 

    DBQueue getDBQueue(int id) { 
     SQLiteDatabase db = this.getReadableDatabase(); 

     Cursor cursor = db.query(TABLE_QUEUE, new String[] { DATABASE_ID, 
       DATABASE_QID, DATABASE_QUEUE }, DATABASE_ID + "=?", 
       new String[] { String.valueOf(id) }, null, null, null, null); 
     if (cursor != null) 
      cursor.moveToFirst(); 

     DBQueue dbqueue = new DBQueue(Integer.parseInt(cursor.getString(0)), 
       cursor.getString(1), cursor.getString(2), cursor.getString(3)); 
     return dbqueue; 
    } 


    public String getAllqid() { 
     Time today = new Time(Time.getCurrentTimezone()); 
     today.setToNow(); 

     String selectQuery = "SELECT * FROM " + TABLE_QUEUE + " WHERE " + DATABASE_DATE + " = '" + today.format("%d %m %Y") + "'"; 

     SQLiteDatabase db = this.getWritableDatabase(); 
     Cursor cursor = db.rawQuery(selectQuery, null); 

     StringBuilder sb = new StringBuilder();  
     if (cursor.moveToFirst()) { 
      do { 
       if (sb.length() > 0) sb.append(','); 
       sb.append(cursor.getString(1)); 
      } while (cursor.moveToNext()); 
     } 

     String result = sb.toString(); 
     return result; 
    } 
    public void deleteDatedDBQueue() { 
     Time today = new Time(Time.getCurrentTimezone()); 
     today.setToNow(); 
     String selectQuery = "SELECT * FROM " + TABLE_QUEUE + " WHERE " + DATABASE_DATE + " != '" + today.format("%d %m %Y") + "'"; ; 

     SQLiteDatabase db = this.getWritableDatabase(); 
     Cursor cursor = db.rawQuery(selectQuery, null); 

     if (cursor.moveToFirst()) { 
      do { 
       db.delete(TABLE_QUEUE, DATABASE_ID + " = ?", 
         new String[] { String.valueOf(Integer.parseInt(cursor.getString(0))) }); 
      } while (cursor.moveToNext()); 
     } 
     db.close(); 
    } 
    public int getDBQueueCount() { 
     String countQuery = "SELECT * FROM " + TABLE_QUEUE; 
     SQLiteDatabase db = this.getReadableDatabase(); 
     Cursor cursor = db.rawQuery(countQuery, null); 
     cursor.close(); 

     return cursor.getCount(); 
    } 
} 

alguien puede por favor dime como arreglar esta fuga?

código completo: http://ijailbreak.me/databasehandler.txt

Respuesta

50

Cada Cursor debería cerrarse cuando haya terminado con él. La forma tradicional de hacer esto es:

Cursor cursor = db.query(...); 
try { 
    // read data from the cursor in here 
} finally { 
    cursor.close(); 
} 

Pero ahora, con try-with-resources, puede ser mucho más concisa:

try (Cursor cursor = db.query(...)) { 
    // read data from the cursor in here 
} 
+0

También creo que es porque la base de datos no está cerrada en varios de los métodos que pueden significar cuando su ayudante abierto sale del alcance, se filtra, entonces en mi respuesta sugiero que el abierto sea un singleton para evitar abrir/problemas cercanos que solo empeorarán cuando intente usarlo en varios hilos :) –

+6

Sí, la conexión de la base de datos siempre debe ser un singleton. –

+0

bien, utilicé este método cada vez que uso Cursor. y agregó algunos db.close(); y creo que soluciona el problema. Gracias ! – Kirma

8

se olvida de cerrar los cursores en varias ocasiones, asegúrese de que siempre cierra el cursor cuando el hecho.

Por ejemplo, la segunda consulta no se cierra el cursor, he TODO'd que para mayor claridad

también no cierra la SQLiteDatabase una vez que su hecho en getDBQueue, getAllqid y getDBQueueCount, si cambia su diseño para hacer su SQLiteOpenHelper un conjunto unitario, entonces no tendrá que cerrar la SQLiteDatabase y evitar la fuga

DBQueue searchDBqid(int id) { 
     SQLiteDatabase db = this.getReadableDatabase(); 

     String selectQuery = "SELECT * FROM " + TABLE_QUEUE + " WHERE " + DATABASE_QID + " = " + id; 

      Cursor cursornum = db.rawQuery(selectQuery, null); 
      int dk = cursornum.getCount(); 
      cursornum.close(); 

      if (dk >0) { 

       // TODO: Close this cursor! 
       Cursor cursor = db.query(TABLE_QUEUE, new String[] { DATABASE_ID, 
         DATABASE_QID, DATABASE_QUEUE, DATABASE_DATE }, DATABASE_QID + "=?", 
         new String[] { String.valueOf(id) }, null, null, null, null); 

       if (cursor != null) cursor.moveToFirst(); 

       DBQueue dbqueue = new DBQueue(Integer.parseInt(cursor.getString(0)), 
         cursor.getString(1), cursor.getString(2), cursor.getString(3)); 
       return dbqueue; 
      } 

     db.close(); 
     return null; 
    } 
0

primera vez la base de datos abierta y por último poner este código.

@Override 
     protected void onDestroy() { 
      // TODO Auto-generated method stub 
     mdb.close(); 
     super.onDestroy(); 
     } 
1

Cada vez que se abre una base de datos (leer o escribir) y el cursor que utiliza recursos de memoria tiene que cancelar la asignación mediante el uso de ".close();" después de su uso termina en cada función de base de datos por ejemplo:

if (cursor != null) cursor.moveToFirst(); 

       DBQueue dbqueue = new DBQueue(Integer.parseInt(cursor.getString(0)), 
         cursor.getString(1), cursor.getString(2), cursor.getString(3)); 
       return dbqueue; 
      } 
cursor.close(); 

     db.close(); 
     return null; 
    } 

DBQueue getDBQueue(int id) { 
     SQLiteDatabase db = this.getReadableDatabase(); 

     Cursor cursor = db.query(TABLE_QUEUE, new String[] { DATABASE_ID, 
       DATABASE_QID, DATABASE_QUEUE }, DATABASE_ID + "=?", 
       new String[] { String.valueOf(id) }, null, null, null, null); 
     if (cursor != null) 
      cursor.moveToFirst(); 

     DBQueue dbqueue = new DBQueue(Integer.parseInt(cursor.getString(0)), 
       cursor.getString(1), cursor.getString(2), cursor.getString(3)); 
cursor.close(); 
db.close(); 
     return dbqueue; 
    } 

y así sucesivamente .... !!