18

わからない記憶障害があります。データベースの取得作業をすべて行うクラスが 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();

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

前もって感謝します。

4

2 に答える 2

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();
}
于 2012-09-25T09:20:18.307 に答える
10

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

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

編集:

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

于 2012-09-25T06:40:52.550 に答える