Недостаточно памяти при распределении курсоров - программирование
Подтвердить что ты не робот

Недостаточно памяти при распределении курсоров

У меня проблема с памятью, которую я не могу понять. У меня есть один класс, который выполняет всю мою базу данных. Ошибка, которая у меня есть, следующая:

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

Сохраняется ли курсор в этом случае?

Спасибо заранее.

4b9b3361

Ответ 1

Вызов 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();
}

Ответ 2

Одной из причин возникновения ошибки Out of Memory является you are not closing your cursor.

Как я вижу, вы вызываете cursor.close(), но это подходящее место, где вы должны вызвать этот метод или проверить, следует ли его закрыть в другом месте.

EDIT:

Если ваша активность managing your Cursor, вы можете рассмотреть возможность остановить ее и закрыть все в методе onPause, а в onResume снова открыть все и снова заполнить.