2012-09-25 18 views
16

Ich habe ein Speicherproblem, das ich nicht herausfinden kann. Ich habe eine Klasse, die alle meine Datenbank-Abruf-Arbeit erledigt. Der Fehler, den ich habe, ist folgendes:Nicht genügend Speicher beim Zuweisen von Cursorn

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

Die Speicherzuordnungsfehler tritt auf, wenn ich dies tun:

mDatabaseInterface.getGraphForLevel(level); 

Ich weiß, dass es ein Leck ist, weil ich diese Methode alle 2,5 Sekunden rufen grob, und die 5 oder 6 erste Anrufe gehen leicht durch. Hier sind die Methoden in meiner DatabaseInterface Klasse:

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

ich viele Methoden, die sich gegenseitig anrufen, aber ich weiß, es ist kein Problem, weil Rekursion diese Klasse in einer anderen App funktioniert. Meine Hauptfrage ist, warum nicht cursor.close() den Cursor freigibt? Wenn ich etwas mache wie:

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

Wird der Cursor in diesem Fall beibehalten?

Vielen Dank im Voraus.

+0

Nur um eine Idee zu bekommen, wie groß sind die Tabellen für Knoten und Kanten? – Matthieu

+0

Sie sind sehr klein für jetzt, 20 Zeilen und 10 Spalten höchstens – chopchop

Antwort

27

Der Aufruf an cursor.close() sollte in einem finally Block sein, falls eine Ausnahme ausgelöst wird, während Sie darüber iterieren.

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

danke Umgebung mit endlich gelöst – chopchop

9

Einer der Gründe für den Fehler "Out of Memory" ist you are not closing your cursor.

Wie ich sehe, rufen Sie cursor.close(), aber es ist der richtige Ort, wo Sie diese Methode aufrufen sollten oder überprüfen Sie, ob Sie es an einem anderen Ort schließen sollten.

EDIT:

Wenn Ihre Aktivität managing your Cursor ist, können Sie prüfen, stoppen sie die Verwaltung und schließen alles in der Methode, und in onResume offen alles einmal und fillData wieder.

+0

siehe meine Bearbeitung – Shrikant

+0

mmm danke Ich habe meinen Code gründlich überprüft und dachte, ich habe es behoben. Aber es kam nach 10 Minuten zurück (viel besser als 10 Sekunden!). Aber jetzt statt 733 oder so Cursor stürzt es mit nur 4 Cursor geöffnet. android.database.CursorWindowAllocationException: Die Cursorfensterzuordnung von 2048 KB ist fehlgeschlagen. # Open Cursors = 4 (# cursors von diesem proc geöffnet = 4) – chopchop

+0

Okay. Wenn Sie also ein globales Objekt des Cursors verwenden, versuchen Sie zunächst, den Inhalt des Cursors zu löschen, und füllen Sie dann die darin enthaltenen Daten erneut auf, so dass der Inhalt des Cursors den Schwellenwert nicht überschreitet. – Shrikant

Verwandte Themen