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 :)希望这可以帮助任何人也。