2012-10-09 5 views
19

i habe Probleme mit SQL-HandlerAndroid SQLite durchgesickert

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. 

von Androidhive Tutorial genommen und individuell auf meine Verwendung

der Tisch sieht aus wie

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

Der Code

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(); 
    } 
} 

Kann jemand Bitte sagen Sie mir, wie Sie dieses Leck beheben können?

vollständige Code: http://ijailbreak.me/databasehandler.txt

Antwort

50

Jeder Cursor sollte geschlossen werden, wenn Sie mit ihm fertig sind. Der traditionelle Weg, dies zu tun ist:

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

Aber jetzt, mit try-with-resources, kann es viel mehr prägnant sein: Dieser Code

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

Ich denke auch, weil die Datenbank nicht in mehreren der Methoden geschlossen ist, die bedeuten könnten, wenn sein offener Helfer außerhalb des Geltungsbereiches geht, leckt es, so in meiner Antwort schlage ich vor, den offenen Helfer ein Singleton zu machen Schließen Sie Probleme, die nur noch schlimmer werden, wenn er versucht, sie über mehrere Threads zu verwenden :) –

+6

Ja, die Datenbankverbindung sollte immer ein Singleton sein. –

+0

ok, ich habe diese Methode jedes Mal benutzt, wenn ich Cursor verwende. und fügte einige db.close() hinzu; und ich denke, es behebt das Problem. Vielen Dank ! – Kirma

8

Sie vergessen Ihre Cursor bei mehreren Gelegenheiten zu schließen, stellen Sie sicher, dass Sie immer den Cursor schließen, wenn Sie fertig sind.

Zum Beispiel kann die zweite Abfrage schließen den Cursor nicht, ich habe es Klarheit TODO'd

Auch schließen Sie nicht die SQLiteDatabase, sobald Ihr getan in getDBQueue, getAllqid und getDBQueueCount, wenn Sie Ihr Design ändern um Ihren SQLiteOpenHelper ein Singleton dann werden Sie nicht die SQLiteDatabase schließen müssen und vermeiden das Leck

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

erstmals offene Datenbank und letzter Put.

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

Jedes Mal, wenn Sie eine Datenbank öffnen (gelesen oder geschrieben) und Cursor, die Speicherressourcen verwendet wird durch die Verwendung werden ausgeplant „.close();“ nach seiner Nutzung endet zB in jeder Datenbank-Funktion:

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; 
    } 

und so weiter .... !!