web-dev-qa-db-ja.com

カーソルを割り当てるときにメモリ不足

理解できないメモリの問題があります。すべてのデータベース取得作業を行う1つのクラスがあります。私が持っているエラーは次のとおりです。

_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.close()がカーソルを解放しないのですか?私が次のようなことをした場合:

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

その場合、カーソルは保持されますか?

前もって感謝します。

17
chopchop

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

メモリ不足エラーが発生する理由の1つは、_you are not closing your cursor_です。

ご覧のとおり、cursor.close()を呼び出していますが、このメソッドを呼び出すか、他の場所で閉じる必要があるかどうかを確認するのに適した場所ですか。

編集:

アクティビティが_managing your Cursor_の場合は、管理を停止してonPauseメソッドですべてを閉じ、onResumeですべてを開いてもう一度fillDataを開くことを検討してください。

9
Shrikant