2012-09-25 18 views
16

मुझे एक स्मृति समस्या है जिसे मैं समझ नहीं सकता। मेरे पास एक वर्ग है जो मेरे सभी डेटाबेस को पुनर्प्राप्त करने का काम करता है। त्रुटि मेरे पास है वह इस प्रकार है:कर्सर आवंटित करते समय मेमोरी से बाहर

android.database.CursorWindowAllocationException: Cursor window allocation of 2048 kb failed. # Open Cursors=733 (# cursors opened by this proc=733) 

स्मृति आवंटन त्रुटि तब होती है जब मैं ऐसा करते हैं:

mDatabaseInterface.getGraphForLevel(level); 

मैं जानता हूँ कि यह एक रिसाव है क्योंकि मैं मोटे तौर पर इस विधि हर 2.5 सेकंड कहते हैं, और 5 या 6 पहली कॉल आसानी से गुजरती हैं। अब यहाँ मेरी DatabaseInterface कक्षा में तरीके हैं:

public Graph getGraphForLevel(Level level) { 

    //get the nodes 
    ArrayList<Node> nodes = new ArrayList<Node>(Arrays.asList(this.getNodesWithLevel(level))); 
    //get the edges 
    ArrayList<Edge> edges = new ArrayList<Edge>(Arrays.asList(this.getEdgesWithNodes(nodes))); 

    return new Graph(nodes, edges); 
} 

public Node[] getNodesWithLevel(Level level) { 

    List<Node> l = new ArrayList<Node>(); 

    Cursor cursor = mDatabase.query("nodes", null, 
      "level = " + wrapSql(String.valueOf(level.getId())), null, null, null, null); 

    while (cursor.moveToNext()) { 
     l.add(parseNodeFromCursor(cursor)); 
    } 

    cursor.close(); 

    return l.toArray(new Node[l.size()]);  
} 

private Node parseNodeFromCursor(Cursor cursor) { 

    Level l = getLevelWithId(cursor.getInt(2)); 

    return new Node(cursor.getInt(0), cursor.getString(1), l, 
      cursor.getInt(4), cursor.getInt(5)); 
} 

मैं तरीकों कि एक दूसरे को फोन का एक बहुत है, लेकिन मैं जानता हूँ कि यह एक प्रत्यावर्तन समस्या है क्योंकि इस वर्ग के किसी अन्य ऐप्स में काम करता है नहीं है। मेरा मुख्य सवाल यह है कि कर्सर को मुक्त क्यों नहीं करता है? अगर मैं कुछ ऐसा करता हूं:

cursor = mDatabase.query(...); 
cursor.moveToNext(); 
Node node = new Node(cursor.getInt()); 
cursor.close(); 

कर्सर उस मामले में बनाए रखा है?

अग्रिम धन्यवाद।

+0

बस एक विचार पाने के लिए, नोड्स और किनारों के लिए टेबल कितने बड़े हैं? – Matthieu

+0

वे अब बहुत छोटे हैं, 20 पंक्तियों और 10 कॉलम अधिकांश – chopchop

उत्तर

27

cursor.close() पर कॉल finally ब्लॉक में होना चाहिए यदि आप इसे अपरिवर्तित करते समय अपवाद फेंक देते हैं।

Cursor cursor = mDatabase.query("nodes", null, 
     "level = " + wrapSql(String.valueOf(level.getId())), null, null, null, null); 
try { 
    while (cursor.moveToNext()) { 
     l.add(parseNodeFromCursor(cursor)); 
    } 
} finally { 
    cursor.close(); 
} 
+0

अंततः इसके हल के साथ धन्यवाद – chopchop

9

मेमोरी त्रुटि से बाहर होने के कारणों में से एक कारण you are not closing your cursor है।

जैसा कि मैं देख सकता हूं, आप cursor.close() पर कॉल कर रहे हैं, लेकिन क्या यह सही जगह है जहां आपको यह विधि कॉल करनी चाहिए या जांचें कि आपको इसे किसी अन्य स्थान पर बंद करना चाहिए या नहीं।

संपादित करें:

तो अपनी गतिविधि managing your Cursor है, तो आप इसे प्रबंध और विधि में सब कुछ बंद करने को रोकने पर विचार कर सकते हैं, और onResume खुला सब कुछ और fillData में एक बार फिर से।

+0

पर कृपया मेरे संपादन – Shrikant

+0

मिमीएम धन्यवाद देखें मैंने पूरी तरह से अपना कोड चेक किया और सोचा कि मैंने इसे ठीक किया है। लेकिन यह 10 मिनट चलने के बाद वापस आया (10 सेकंड से काफी बेहतर!)। लेकिन अब 733 या तो कर्सर के बजाय यह केवल 4 कर्सर खोले गए हैं। android.database.CursorWindowAllocationException: कर्सर विंडो आवंटन 2048 केबी विफल रहा। # ओपन कर्सर = 4 (इस कर्सर = 4 द्वारा खोले गए # कर्सर) – chopchop

+0

ठीक है। तो अब, यदि आप कर्सर की वैश्विक वस्तु का उपयोग कर रहे हैं, तो पहले कर्सर की सामग्री को साफ़ करने का प्रयास करें और फिर डेटा को फिर से भरें, ताकि कर्सर की सामग्री थ्रेसहोल्ड से अधिक न हो। – Shrikant