10

To doprowadza mnie do szału już od kilku dni. Mam aplikację na Androida, która jest dość skomplikowana. Używa wielu wątków do pobierania danych z serwera i zapełniania bazy danych SQLite. Używam singleton odwołania do mojego rozszerzenia SQLiteOpenHelper. Otwieram i zamykam bazę danych w każdej z moich aktywności.Android SQLite SQLiteOpenHelper IllegalStateException - DB Błąd już zamknięty

Błąd pojawia się TYLKO w sytuacji, gdy mam 4 aktywności, a następnie spróbuję się wycofać. Próbowałem różnych sposobów otwierania i zamykania bazy danych, w tym przesuwania zamknięcia od metody onDestroy() do metody onPause(), a także dodawania kolejnego otwarcia do metody onResume().

Warto też wspomnieć, moje działania w ogromnym stopniu korzystają z ListViews i ExpandableListViews, co rozumiem może spowodować bazę do bliskich na podstawie tego artykułu: http://darutk-oboegaki.blogspot.com/2011/03/sqlitedatabase-is-closed-automatically.html

Poszedłem poprzez kod i upewnić się, że jestem albo zamknięcie wszystkich moich kursorów, albo, jeśli są one przypisane do adaptera, wywołanie funkcji startManagingCursor().

Czy ktoś ma pojęcia, co się dzieje?

java.lang.RuntimeException: Unable to resume activity {com.fieldone/com.fieldone.DispatchActivity}: java.lang.IllegalStateException: database /data/data/com.fieldone/databases/InterstateAirConditioning-1602814322.db already closed 
    at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3347) 
    at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:3362) 
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2162) 
    at android.os.Handler.dispatchMessage(Handler.java:99) 
    at android.os.Looper.loop(Looper.java:144) 
    at android.app.ActivityThread.main(ActivityThread.java:4937) 
    at java.lang.reflect.Method.invokeNative(Native Method) 
    at java.lang.reflect.Method.invoke(Method.java:521) 
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626) 
    at dalvik.system.NativeStart.main(Native Method) 
Caused by: java.lang.IllegalStateException: database /data/data/com.fieldone/databases/InterstateAirConditioning-1602814322.db already closed 
    at android.database.sqlite.SQLiteProgram.bindString(SQLiteProgram.java:237) 
    at android.database.sqlite.SQLiteQuery.requery(SQLiteQuery.java:145) 
    at android.database.sqlite.SQLiteCursor.requery(SQLiteCursor.java:567) 
    at android.app.Activity.performRestart(Activity.java:3836) 
    at android.app.Activity.performResume(Activity.java:3857) 
    at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3337) 
    ... 10 more 

UPDATE: Naprawiłem problem, ale nie wiem, dlaczego to naprawił. Więc może ktoś tam wie lub może wyjaśnić.

Kiedy jestem w czwartej czynności stosu działań, próbowałem zamknąć db za pomocą db.close(). Bez względu na to, WHERE I put to, w onCreate po otrzymaniu potrzebnych danych, lub w onStop lub onDestroy, spowoduje to błąd. Jeśli NIE zamknę db, nie mam problemu. Oznacza to, że db automatycznie się zamyka. Dziwne jest to, mimo że używam expandableListView w tym ostatnim działaniu, NIE używam cursorAdapter. Ktoś ma jakieś myśli? Chciałbym to zrozumieć.

Odpowiedz

19

Ponieważ kwestia ta ma zdobyć sporo uwagi, chciałem go odebrać i opisać to, co się nauczyłem i co pracował dla mnie, aby rozwiązać ten problem w moim dużym, aplikacji bazy danych napędzane:

  1. NIE używaj zarządzanych kursorów. Jest powód, dla którego są przestarzałe. Są całkowicie problematyczne. Realistycznie, jest bardzo mało scenariuszy, w których tak naprawdę trzeba użyć zarządzanego kursora. Zamiast tego uruchom zapytanie i zapełnij obiekt wynikami. Jeśli pytasz o wiele wierszy, utwórz ArrayList <> swojego obiektu, aby pomieścił wszystkie wiersze. Teraz, co robię, tworzę funkcję, która uruchamia zapytanie i przekazuje mi z powrotem moją ArrayList <> zamiast kursora w powrocie. Zamykam kursor w funkcji i skończę. W przypadku ListViews nie będzie już można korzystać z SimpleCursorAdapter. Po prostu przekonwertuj te wszystkie do BaseAdapter i użyj swojego obiektu ArrayList <>, aby go wypełnić.

  2. NIE ZAPOMNIJ, ABY ZAMKNĄĆ WSZYSTKICH TWÓJ KURSORÓW. Może to również spowodować spustoszenie w połączeniach db aplikacji. Myślałem, że to robię, ale na pewno znalazłem miejsce, w którym nie zamykałem wyraźnie kursora. Tak więc przejdź do swojej aplikacji i sprawdź dokładnie wszystkie.

Używam również pojedynczego obiektu DatabaseHelper.Deklaruję statyczny obiekt DatabaseHelper w mojej klasie SQLiteOpenHelper, dzięki czemu za każdym razem otrzymuję to samo wystąpienie.

Mam teraz stabilną aplikację, która nie ma już błędów DB. Mam nadzieję, że te informacje są pomocne dla niektórych z was.

2

użyć CursorAdapter.changeCursor (null), może spowolnić pojawianie się tego błędu, ale nie może całkowicie rozwiązać problom, nieznany okres czasu pojawi się ponownie. To także doprowadza mnie do szaleństwa!

1

Miałem również ten sam problem "db już zamknięty wyjątek z nieprawidłową instrukcję kursor w fillWindow() i IllegalStatementException". To co zrobiłem to umieściłem kursor (w/c również pochodzi z SimpleCursorAdapter) do zmiennej instancji zamiast zmiennej metody, a następnie na moje metody onStop i onPause, które nazywam stopManagingCursor, a następnie na moje metody onResume i onStart, które nazywam startManagingCursor.

Rozwiązał mój problem dla mnie i nie znalazłem żadnych komunikatów o błędach lub ostrzeżeniach w moim logcat po tym :) Mam nadzieję, że to pomoże każdemu również.