Android SQLite SQLiteOpenHelper IllegalStateException - 数据库已经关闭错误

时间:2011-06-30 13:57:21

标签: android database sqlite illegalstateexception sqliteopenhelper

这让我疯狂了好几天了。我有一个非常复杂的Android应用程序。它使用多个线程从服务器提取数据并填充SQLite数据库。我正在使用单例来引用我的SQLiteOpenHelper扩展。我在每个活动中打开和关闭数据库。

错误仅发生在我4次活动深度然后尝试退出的情况下。我已经尝试了各种方法来打开和关闭数据库,包括将关闭从onDestroy()移动到onPause()方法,还添加另一个打开到onResume()。

另外值得注意的是,我的活动大量使用ListViews和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()关闭数据库。无论我把它放在哪里,在我得到我需要的数据之后的onCreate中,或者在onStop或onDestroy中,它都会产生这个错误。如果我不关闭数据库,我没有问题。因此,某些事情导致数据库自动关闭。奇怪的是,虽然我在最后的活动中使用了expandableListView,但我没有使用cursorAdapter。有人有什么想法?很想明白这一点。

3 个答案:

答案 0 :(得分:20)

由于这个问题引起了很多关注,我想回答它并描述我学到了什么,以及在我的大型数据库驱动的应用程序中纠正这个问题对我有用:

  1. 请勿使用托管游标。这是他们被弃用的原因。他们完全有问题。实际上,实际上您需要使用托管游标的情况非常少。而是运行查询并使用结果填充对象。如果您要查询多行,请创建一个ArrayList<>您的对象保存所有行。我现在做的是创建一个运行查询的函数,并将我传回给我的ArrayList<>而不是返回中的光标。我关闭了函数中的光标,我就完成了。对于ListView,您将无法再使用SimpleCursorAdapter。只需将所有这些转换为BaseAdapter并使用您的ArrayList<>填充它的对象。

  2. 不要忘记关闭所有你的游标。这也会对您应用的数据库连接造成严重破坏。我以为我这样做了,但果然,找到了一个我没有明确关闭光标的地方。所以,浏览你的应用并仔细检查所有这些。

  3. 我也在使用单例DatabaseHelper对象。我在我的SQLiteOpenHelper类中声明了一个静态的DatabaseHelper对象,这样我每次都会获得相同的实例。

    我现在有一个稳定运行的应用程序,不再出现这些数据库错误。我希望这些信息对你们中的一些人有所帮助。

答案 1 :(得分:2)

使用CursorAdapter.changeCursor(null),可以减缓这个bug的出现,但不能完全解决问题,未知的时间段会再次出现。   这也让我发疯了!

答案 2 :(得分:1)

我也有同样的问题'db已经关闭了异常,fillWindow()和IllegalStatementException中的游标无效语句'。我所做的是将光标(w / c也来自SimpleCursorAdapter)放到实例变量而不是方法变量然后放在我的onStop和onPause方法上我调用stopManagingCursor然后调用onResume和onStart方法我调用startManagingCursor。

它为我解决了我的问题,之后我没有在我的logcat中发现任何错误或警告消息:)希望这对任何人都有帮助。