2012-10-09 11 views
19

मैं एसक्यूएल हैंडलर के साथ होने समस्याएंड्रॉयड SQLite लीक

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. 

Androidhive ट्यूटोरियल से लिया और अपने उपयोग के लिए अनुकूलित

तालिका

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

कोड की तरह

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

कोई भी कर सकता है कृपया मुझे बताओ कि इस रिसाव को कैसे ठीक किया जाए?

पूर्ण कोड: http://ijailbreak.me/databasehandler.txt

उत्तर

50

जब आप इसे पूर्ण कर लें प्रत्येक Cursor बंद किया जाना चाहिए से बचने के लिए की जरूरत नहीं होगी। यह करने के लिए पारंपरिक तरीका है:

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

लेकिन अब, try-with-resources साथ, यह बहुत अधिक संक्षिप्त हो सकता है:

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

मैं यह भी सोचता हूं क्योंकि डेटाबेस कई तरीकों से बंद नहीं होता है, जिसका अर्थ हो सकता है कि जब उसका खुला सहायक गुंजाइश से बाहर हो जाता है, तो यह मेरे उत्तर में होता है, इसलिए मैं खुला हेल्पर को सिंगलटन को खुले/करीबी मुद्दे जो केवल खराब हो जाएंगे जब वह इसे कई धागे में उपयोग करने का प्रयास करता है :) –

+6

हां, डेटाबेस कनेक्शन हमेशा एक सिंगलटन होना चाहिए। –

+0

ठीक है, हर बार जब मैं कर्सर का उपयोग करता हूं तो मैंने इस विधि का उपयोग किया था। और कुछ db.close() जोड़ा; और मुझे लगता है कि यह समस्या को ठीक करता है। धन्यवाद ! – Kirma

8

आप कई मौकों पर अपने कर्सर को बंद करने के भूल जाते हैं, सुनिश्चित करें कि आप हमेशा कर्सर को बंद जब आपके किया हो।

उदाहरण के लिए, दूसरी क्वेरी कर्सर बंद नहीं होती है, मैं स्पष्टता

इसके अलावा के लिए यह TODO'd है आप एक बार अपने SQLiteDatabasegetDBQueue, getAllqid और getDBQueueCount में किया बंद नहीं करते, यदि आप अपने डिजाइन में परिवर्तन अपने SQLiteOpenHelper एक सिंगलटन बनाने के लिए तो आप SQLiteDatabase को बंद करने और रिसाव

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

पहली बार खुला डेटाबेस और पिछले पुट इस कोड।

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

हर बार जब आप एक डेटाबेस को खोलने (पठनीय या लिखने योग्य) और कर्सर जो स्मृति संसाधनों का उपयोग करके पुनः आवंटित की जाती किया जाना है का उपयोग करता है ".close();" इसके उपयोग प्रत्येक डेटाबेस समारोह जैसे में समाप्त होने के बाद:

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

और इतने पर .... !!

संबंधित मुद्दे