2014-04-30 20 views
11

Mam dziwny problem z bazą danych Android i kursorami. Czasami (bardzo rzadko) zdarza się, że dostałem zgłoszenie awarii od klientów. Trudno się domyślić, dlaczego tak się dzieje, ponieważ mam ~ 150 000 aktywnych użytkowników i może 1 raport na tydzień, więc jest to drobny błąd. Oto wyjątek:Baza danych Androida - Nie można wykonać tej operacji, ponieważ pula połączeń została zamknięta

STACK_TRACE=java.lang.IllegalStateException: Cannot perform this operation because the connection pool has been closed. 
at android.database.sqlite.SQLiteConnectionPool.throwIfClosedLocked(SQLiteConnectionPool.java:962) 
at android.database.sqlite.SQLiteConnectionPool.waitForConnection(SQLiteConnectionPool.java:599) 
at android.database.sqlite.SQLiteConnectionPool.acquireConnection(SQLiteConnectionPool.java:348) 
at android.database.sqlite.SQLiteSession.acquireConnection(SQLiteSession.java:894) 
at android.database.sqlite.SQLiteSession.executeForCursorWindow(SQLiteSession.java:834) 
at android.database.sqlite.SQLiteQuery.fillWindow(SQLiteQuery.java:62) 
at android.database.sqlite.SQLiteCursor.fillWindow(SQLiteCursor.java:144) 
at android.database.sqlite.SQLiteCursor.getCount(SQLiteCursor.java:133) 
at sk.mildev84.agendareminder.a.c.a(SourceFile:169) 

Przed każdym kursorem "iteracji i odkrywania" Używam tego kodu, aby upewnić się, że wszystko jest w porządku:

db = instance.getWritableDatabase(); 
cursor = db.rawQuery(selectQuery, null); 

if (isCursorEmptyOrNotPrepared(cursor)) { 
    ... 
    } 

private synchronized boolean isCursorEmptyOrNotPrepared(Cursor cursor) { 
     if (cursor == null) 
      return true; 

     if (cursor.isClosed()) 
      return true; 

     if (cursor.getCount() == 0) // HERE IT CRASHES 
      return true; 

     return false; 
    } 

I to spada na linii:

if (cursor.getCount() == 0) 

Ktoś wie dlaczego? Myślę, że sprawdzam wszystkie możliwe wyjątki i warunki ... Dlaczego moja aplikacja się zawiesza?

PS: Wszystkie metody bazy danych są zsynchronizowane, a ja poprawnie otwieram i zamykam bazę danych/kursory we wszystkich przypadkach, sprawdziłem to wiele razy.

+0

Napisz więcej kodu i pełnego stosu. Otrzymujesz to wykroczenie -> masz błąd gdzieś – nikis

+0

zaktualizowane pytanie. – qkx

+0

Nie ma potrzeby zamykania bazy danych. Android sobie z tym poradzi. Przeczytaj to świetne wyjaśnienie tutaj ...http://stackoverflow.com/questions/14002022/android-sq-lite-closed-exception/25379071#25379071 – Nepster

Odpowiedz

0

Wystarczy usunąć Usuń db.close()

24

Problem
Jeśli spróbujesz kolejnej operacji po zamknięciu bazy danych, to daje to exception.Because db.close(); uwalnia odniesienie do obiektu, zamykając obiekt, jeśli ostatnie odwołanie zostało zwolnione.

Rozwiązanie
Zachowaj pojedynczą instancję SQLiteOpenHelper (Singleton) w kontekście statycznym. Zrób leniwą inicjalizację, i synchronize tą metodą. Takich jak

i nie musisz go zamykać? Gdy aplikacja zostanie zamknięta, zwolni odniesienie do pliku, nawet jeśli będzie się z nim trzymał.
Oznacza to, że nie należy zamykać bazy danych, ponieważ będzie ona ponownie używana w następnym połączeniu. więc po prostu usunąć

db.close(); 

Więcej informacji można znaleźć w Single SQLite connection

0

miałem ten problem zbyt. moja klasa SQLiteOpenHelper była Singleton, a także zamykanie db po każdej operacji CRUD. Po robię moje metod (CRUD) zsynchronizowanych w mojej klasie SQLiteOpenHelper, nie pojawia się błąd dłużej :)

0

sam problem wystąpił do mnie, więc po przeczytaniu explanation usunąłem
db.close();
z
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs)
i
public int delete(Uri uri, String selection, String[] selectionArgs) Metoda ContentProvider
Brak potrzeby db.close(), ponieważ sam ContentProvider zajmuje się zamykaniem bazy danych.