Не удалось выделить CursorWindow

Я работаю в базе данных SQLite3 в своем приложении для Android. Я просто прочитал из предварительно заполненной базы данных, которая имеет 200 тыс. Строк и 14 столбцов. Записи - это слова. Тип данных всех столбцов - это текст. Запрос слов до 11 букв (например, ABANDONMENT) работает нормально. Но на 12 или больше (например, ABANDONMENTS) приложение выйдет из строя. Вот logcat:

Could not allocate CursorWindow '//data//data//com.example.myapp//databases//database.sqlite' of size 2097152 due to error -12.
threadid=11: thread exiting with uncaught exception (group=0x40adf9f0)
FATAL EXCEPTION: Thread-2883
android.database.CursorWindowAllocationException: Cursor window allocation of 2048 kb failed. # Open Cursors=861 (# cursors opened by this proc=861)
at android.database.CursorWindow.<init>(CursorWindow.java:104)
at android.database.AbstractWindowedCursor.clearOrCreateWindow(AbstractWindowedCursor.java:198)
at android.database.sqlite.SQLiteCursor.fillWindow(SQLiteCursor.java:162)
at android.database.sqlite.SQLiteCursor.getCount(SQLiteCursor.java:156)
at android.database.AbstractCursor.moveToPosition(AbstractCursor.java:161)
at android.database.AbstractCursor.moveToFirst(AbstractCursor.java:201)
at com.example.myapp.MainActivity.query(MainActivity.java:815)
at com.example.myapp.MainActivity$2.run(MainActivity.java:356)
at java.lang.Thread.run(Thread.java:856)

код:

query = "select * from words where col_1 = \"" + (myWord)+ "\";";
cursor = database.rawQuery(query, null);
if (cursor != null)                                          
    cursor.moveToFirst(); // line 815
if (!cursor.isAfterLast()) {
    do {
        for (i = 1; i < cursor.getColumnCount(); i++) {
            temp = cursor.getString(i);
            //other stuff
        }
    } while (cursor.moveToNext());
    cursor.close();
}

Итак, что означает ошибка и почему приложение сбой?

Ответ 1

Я запросил в цикле. И закрытие курсора внутри цикла, а не вне решения проблемы.

Ответ 2

Ошибка -12 означает утечку курсора. Pls попробуйте закрыть его следующим образом:

try {....} finally {  cursor.close();}

Ответ 3

Android-курсоры считывают все результаты запроса в память и имеют ограничение в 1 МБ для этих данных.

Этот лимит был выбран, потому что этот объем данных, скорее всего, заставит ваше приложение работать вяло на мобильном устройстве.

Вы должны, если возможно:

  • выполнять вычисления не в вашем коде, а в SQL;
  • запрашивать только те данные, которые вам нужны (т.е. не использовать SELECT *, а получать только нужные столбцы и использовать фильтр WHERE);
  • прочитайте данные меньшими порциями.