10

這幾天讓我瘋狂了幾天。我有一個非常複雜的Android應用程序。它使用多個線程從服務器提取數據並填充SQLite數據庫。我正在使用一個單例來引用我的SQLiteOpenHelper的擴展。我在每個活動中打開和關閉數據庫。Android SQLite SQLiteOpenHelper IllegalStateException - 數據庫已關閉錯誤

錯誤只發生在當我4次活動很深並且嘗試退出的情況下。我嘗試了各種打開和關閉數據庫的方法,包括將onDestroy()關閉移動到onPause()方法,並向onResume()添加另一個打開的方法。

另外值得注意的是,我的活動大量使用列表視圖和ExpandableListViews,我理解可能導致數據庫關閉基於此文章:http://darutk-oboegaki.blogspot.com/2011/03/sqlitedatabase-is-closed-automatically.html

我已經通過代碼不見了,確信我是要麼關閉我的所有遊標,要麼將它們分配給適配器,調用startManagingCursor()。

有沒有人知道發生了什麼?

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 

更新:我已經解決了這一問題,但不知道爲什麼這個固定。所以,也許有人知道或可以解釋。

當我在活動堆棧的第4個活動時,我試圖通過db.close()關閉db。無論我在哪裏放置這個,在獲得我需要的數據之後,在onCreate中,或者在onStop或onDestroy中,它都會產生這個錯誤。如果我不關閉分貝,我沒有問題。所以,有些東西會導致數據庫自動關閉。奇怪的是,雖然我在這個最後的活動中使用了expandableListView,但我並沒有使用cursorAdapter。任何人有任何想法?很想理解這一點。

回答

19

既然這個問題已經得到廣泛關注的問題,我想回答這個問題,並說明我已經學會了,什麼工作對我來說,糾正我的大,數據庫驅動的應用程序這個問題:

  1. 不要使用託管遊標。他們被棄用的原因是有原因的。他們完全有問題。實際上,無論如何,你實際上需要使用託管遊標的場景很少。相反,運行你的查詢並用結果填充一個對象。如果您要查詢多行,請創建一個ArrayList對象以保存所有行。我現在所做的是創建一個運行查詢的函數,並將我的ArrayList返回給我,而不是返回中的遊標。我關閉了函數內的光標,我完成了。對於ListViews,您將不再能夠使用SimpleCursorAdapter。只需將所有這些轉換爲BaseAdapter並使用ArrayList對象來填充它。

  2. 不要忘記關閉所有的遊標。這也會對應用程序的數據庫連接造成嚴重破壞。我以爲我正在這樣做,但是,果然,發現了一個地方,我沒有明確地關閉遊標。所以,通過你的應用程序,並仔細檢查所有的。

我還使用了單例DatabaseHelper對象。我在SQLiteOpenHelper類中聲明瞭一個靜態的DatabaseHelper對象,以便每次都得到相同的實例。

我現在有一個穩定的運行應用程序,不會再出現這些數據庫錯誤。我希望這些信息對你們中的一些人有幫助。

2

使用CursorAdapter.changeCursor(null),可以減緩這個bug的出現,但不能完全解決問題,未知的時間段會再次出現。 這也讓我瘋狂!

1

我也有同樣的問題'db已經關閉異常,在fillWindow()和IllegalStatementException'中使用遊標無效語句。我做的是我把我的光標(W/C也來自SimpleCursorAdapter)到一個實例變量,而不是一個方法變量,然後在我的onStop和onPause方法,我調用stopManagingCursor,然後在我的onResume和onStart方法,我叫startManagingCursor。

它解決了我的問題,我沒有發現任何錯誤或警告消息後,我的logcat :)希望這可以幫助任何人也。