2013-08-09 8 views
31

मुझे close the connection और close the cursor जैसी कई चीज़ें मिलीं, लेकिन मैं ये सब कुछ करता हूं। फिर भी SQLite कनेक्शन लीक और मैं इस तरह एक चेतावनी मिलती है:SQLite कनेक्शन लीक हो गया है हालांकि सबकुछ बंद हो गया है

DatabaseManager dbm = new DatabaseManager(this); 

मेरी डेटाबेस का कोड:

A SQLiteConnection object for database was leaked! 

मैं इस एक डेटाबेस प्रबंधक, जो मैं निम्नलिखित कोड के साथ मेरी गतिविधियों में कॉल प्रबंधक वर्ग अब इस प्रकार है:

:

public class DatabaseManager { 

    private static final int DATABASE_VERSION = 9; 
    private static final String DATABASE_NAME = "MyApp"; 
    private Context context = null; 
    private DatabaseHelper dbHelper = null; 
    private SQLiteDatabase db = null; 


    public static class DatabaseHelper extends SQLiteOpenHelper { 

     public DatabaseHelper(Context context) { 
      super(context, DATABASE_NAME, null, DATABASE_VERSION); 
     } 

     @Override 
     public void onCreate(SQLiteDatabase db) { 

        //create database tables 
     } 

     @Override 
     public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 
         //destroy and recreate them 
     } 

    } 

    public DatabaseManager(Context ctx) { 
     this.context = ctx; 
    } 

    private DatabaseManager open() throws SQLException { 
     dbHelper = new DatabaseHelper(context); 
     db = dbHelper.getWritableDatabase(); 

     if (!db.isReadOnly()) { 
      db.execSQL("PRAGMA foreign_keys = ON;"); 
     } 

     return this; 
    } 

    private void close() { 
     dbHelper.close(); 
    } 
} 

जब मैं एक डेटाबेस विधि कॉल, मैं निम्नलिखित काम करते हैं 10

public Object getData() { 

    open(); 

      //... database operations take place ... 

    close(); 

    return data; 
} 

लेकिन जैसा कि मैंने कहा, मुझे अभी भी यह SQLite कनेक्शन लीक चेतावनी मिलती है।

मैं क्या गलत कर रहा हूं?

private DatabaseManager open() throws SQLException { 
    dbHelper = new DatabaseHelper(context); 
    db = dbHelper.getWritableDatabase(); 

से:

+0

मुझे लगता है कि आप केवल अपनी DBHelper बंद कर रहे हैं, लेकिन नहीं डाटाबेस ही – Opiatefuchs

+0

मुझे लगता है कि आप db.close बुलाना चाहिए () भी –

+0

कोई फर्क नहीं पड़ता, अगर मैं ऐसा करता हूं या नहीं। मैं वैसे भी संदेश प्राप्त करूंगा। लेकिन मैंने कहीं पढ़ा है, कि आपको ऐसा करने की आवश्यकता नहीं है, जब आप dbHelper.close() – flp

उत्तर

113

प्रशस्ति पत्र में बोल्ड फ़ॉन्ट अपने कोड में इस हिस्से से मेल खाती है http://www.androiddesignpatterns.com/2012/05/correctly-managing-your-sqlite-database.html

कार्य # 1: एक सार फैक्टरी का प्रयोग करें SQLiteOpenHelper

इन्स्तांत करने के लिए

एक स्थिर आवृत्ति चर के रूप में अपने डेटाबेस सहायक को घोषित करें और सिंगलटन प्रोप की गारंटी के लिए सार फैक्टरी पैटर्न का उपयोग करें erty। नीचे नमूना कोड आपको पर डेटाबेसहेल्पर क्लास को सही तरीके से डिज़ाइन करने के बारे में एक अच्छा विचार देना चाहिए।

स्थैतिक कारखाना मिलता है इंस्टेंस विधि यह सुनिश्चित करता है कि केवल एक डेटाबेसहेल्पर किसी भी समय किसी भी समय मौजूद रहेगा। यदि mInstance ऑब्जेक्ट प्रारंभ नहीं किया गया है, तो एक बनाया जाएगा। अगर किसी के पास पहले से ही बनाया गया है तो इसे वापस कर दिया जाएगा।

आपको new DatabaseHelper(context) के साथ उपयोग करके अपने सहायक ऑब्जेक्ट को प्रारंभ नहीं करना चाहिए।
इसके बजाय, हमेशा DatabaseHelper.getInstance(context) का उपयोग करें, क्योंकि यह गारंटी देता है कि केवल एक डेटाबेस सहायक पूरे एप्लिकेशन के जीवन चक्र में मौजूद होगा।

public static class DatabaseHelper extends SQLiteOpenHelper { 

    private static DatabaseHelper mInstance = null; 

    private static final String DATABASE_NAME = "database_name"; 
    private static final String DATABASE_TABLE = "table_name"; 
    private static final int DATABASE_VERSION = 1; 

    public static DatabaseHelper getInstance(Context ctx) { 

    // Use the application context, which will ensure that you 
    // don't accidentally leak an Activity's context. 
    // See this article for more information: http://bit.ly/6LRzfx 
    if (mInstance == null) { 
     mInstance = new DatabaseHelper(ctx.getApplicationContext()); 
    } 
    return mInstance; 
    } 

    /** 
    * Constructor should be private to prevent direct instantiation. 
    * make call to static factory method "getInstance()" instead. 
    */ 
    private DatabaseHelper(Context ctx) { 
    super(ctx, DATABASE_NAME, null, DATABASE_VERSION); 
    } 
} 
+1

समस्या को ठीक करने के लिए प्रतीत होता है। मैं आगे की जांच करूँगा – flp

+1

ग्रेट उत्तर। कई इरादों के साथ काम करते समय मैं इस समस्या में भाग गया, सभी एक साथ दो अलग-अलग डेटाबेसों में काम कर रहे थे। मैंने दो अलग फैक्ट्री विधियों को छोड़कर इस जवाब का इस्तेमाल किया। सभी मेमोरी रिसाव त्रुटियों को मंजूरी दे दी। इसमें निष्पादन समय में आधे सेकेंड या दो जोड़े गए थे, संभवतः क्योंकि अब मेरे पास एकाधिक डेटाबेस उदाहरण एक साथ खुलते नहीं हैं। –

+1

यह मेरे लिए एक ही समस्या तय करता है। –

1
private void method() { 
     Cursor cursor = query(); 
     if (flag == false) { // WRONG: return before close() 
      return; 
     } 
     cursor.close(); 
    } 

अच्छा अभ्यास इस तरह होना चाहिए:

private void method() { 
     Cursor cursor = null; 
     try { 
      cursor = query(); 
     } finally { 
      if (cursor != null) 
       cursor.close(); // RIGHT: ensure resource is always recovered 
     } 
    } 
संबंधित मुद्दे