2013-07-05 13 views
12

Używam bazy danych SQLite3 w mojej aplikacji dla systemu Android. Właśnie czytałem ze wstępnie wypełnionej bazy danych, która ma 200 tys. Wierszy i 14 kolumn. Wpisy to słowa. Typem danych wszystkich kolumn jest tekst. Zapytanie o słowa do 11 liter (np. ABANDONMENT) działa dobrze. Ale dla 12 lub więcej (np. ABANDONMENTS) aplikacja się zawiesza. Oto logcat:Nie można przydzielić narzędzia CursorWindow

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) 

Kod:

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

Więc co robi błąd oznacza i dlaczego jest to aplikacja zawiesza się?

+1

Pełny kod byłby pomocny. Czy zamykasz kursor po samodzielnym zarządzaniu, dlaczego nie po prostu wywołaj kursor.moveToNext() zamiast! Cursor.isAfterLast() –

+0

Pełny kod aplikacji to 1000 linii. cursor.isAfterLast służy do sprawdzania, czy kursor przeszedł wszystkie wyniki i czy może się zatrzymać. –

+0

Czy zamykasz kursor wewnątrz pętli while? –

Odpowiedz

12

Występowałem w pętli. Zamknięcie kursora w pętli, a nie na zewnątrz rozwiązało problem.

3

Kursory Android odczytują wszystkie wyniki zapytania w pamięci i mają limit 1 MB dla tych danych.

Ten limit został wybrany, ponieważ ta ilość danych może sprawić, że aplikacja będzie działać wolno na urządzeniu mobilnym.

należy, jeśli to możliwe:

  • zrobić obliczeń nie w kodzie, ale w SQL;
  • zapytanie tylko o te dane, których potrzebujesz (tj. Nie używaj SELECT *, ale uzyskaj tylko potrzebne kolumny i użyj filtru WHERE);
  • odczytać dane w mniejszych porcjach.
+0

To niemożliwe. Wszystkie wiersze są unikalne w tabeli. Tak więc zapytanie daje tylko jeden wynik. –

+0

Z pewnością otrzymujesz więcej niż jeden rekord. Jaki jest wynik równoważnika "SELECT COUNT (*) ..."? –

18

Błąd -12 oznacza przeciek kursora. Pls spróbuj zamknąć w następujący sposób:

try {....} finally { cursor.close();} 
Powiązane problemy