11

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

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

另外值得注意的是,我的活动大量使用了 ListViews 和 ExpandableListViews,据我了解,这可能会导致数据库根据这篇文章关闭: http: //darutk-oboegaki.blogspot.com/2011/03/sqlitedatabase-is-closed-自动.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 中,它都会产生这个错误。如果我不关闭数据库,我就没有问题。因此,某些原因导致数据库自动关闭。奇怪的是,虽然我在最后的活动中使用了可扩展列表视图,但我没有使用 cursorAdapter。有人有什么想法吗?很想了解这一点。

4

3 回答 3

20

由于这个问题引起了很多关注,我想回答它并描述我学到的东西以及在我的大型数据库驱动应用程序中解决这个问题的方法:

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

  2. 不要忘记关闭所有光标。这也可能对您的应用程序的数据库连接造成严重破坏。我以为我正在这样做,但果然发现了一个我没有明确关闭游标的地方。因此,请浏览您的应用并仔细检查所有这些。

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

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

于 2011-10-27T17:38:28.380 回答
2

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

于 2011-08-17T10:24:16.633 回答
1

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

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

于 2012-04-10T18:37:22.163 回答