I have a memory problem that I can't figure out. I have one class that does all my database retrieving work. The error I have is the following:
android.database.CursorWindowAllocationException: Cursor window allocation of 2048 kb failed. # Open Cursors=733 (# cursors opened by this proc=733)
The memory allocation error occurs when I do this:
mDatabaseInterface.getGraphForLevel(level);
I know it's a leak because I call this method every 2.5 seconds roughly, and the 5 or 6 first calls go through easily. Now here are the methods in my DatabaseInterface class:
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));
}
I have a lot of methods that call each other but I know it's not a recursion problem because this class works in another app. My main question is why doesn't cursor.close()
liberate the cursor? If I do something like:
cursor = mDatabase.query(...);
cursor.moveToNext();
Node node = new Node(cursor.getInt());
cursor.close();
Is the cursor retained in that case?
Thanks in advance.
The call to cursor.close()
should be in a finally
block in case an exception is thrown while you're iterating over it.
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();
}
One of the reasons for occurring Out of Memory error is you are not closing your cursor
.
As I can see, you are calling cursor.close()
, but is it the right place where you should call this method or check if you should close it on some other place.
EDIT:
If your activity is managing your Cursor
, you may consider stop managing it and closing everything in the onPause
method, and in onResume
open everything up and fillData once again.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With