例外:尝试获取关闭SQLiteClosable的引用

Com*_*are 43 android

我在5月份在[android-developers] Google Group上发布了这个帖子.我从来没有收到回复,直到上周我的一个学生做了之后才能重现这个问题.我想我会把它发布在这里,看看它是否为任何人敲响了任何铃声.

在我的一个代码示例中,我有以下方法:

static Cursor getAll(SQLiteDatabase db, String orderBy) {
        return(db.rawQuery("SELECT * FROM restaurants "+orderBy, null));

}
Run Code Online (Sandbox Code Playgroud)

当我运行它时,偶尔会得到这个:

05-01 14:45:05.849: ERROR/AndroidRuntime(1145):
java.lang.IllegalStateException: attempt to acquire a reference on a
close SQLiteClosable
05-01 14:45:05.849: ERROR/AndroidRuntime(1145):     at
android.database.sqlite.SQLiteClosable.acquireReference(SQLiteClosable.java:31)
05-01 14:45:05.849: ERROR/AndroidRuntime(1145):     at
android.database.sqlite.SQLiteProgram.<init>(SQLiteProgram.java:56)
05-01 14:45:05.849: ERROR/AndroidRuntime(1145):     at
android.database.sqlite.SQLiteQuery.<init>(SQLiteQuery.java:49)
05-01 14:45:05.849: ERROR/AndroidRuntime(1145):     at
android.database.sqlite.SQLiteDirectCursorDriver.query(SQLiteDirectCursorDriver.java:49)
05-01 14:45:05.849: ERROR/AndroidRuntime(1145):     at
android.database.sqlite.SQLiteDatabase.rawQueryWithFactory(SQLiteDatabase.java:1118)
05-01 14:45:05.849: ERROR/AndroidRuntime(1145):     at
android.database.sqlite.SQLiteDatabase.rawQuery(SQLiteDatabase.java:1092)
05-01 14:45:05.849: ERROR/AndroidRuntime(1145):     at
apt.tutorial.Restaurant.getAll(Restaurant.java:14)
Run Code Online (Sandbox Code Playgroud)

这对我来说毫无意义.数据库肯定是开放的.这 SQLiteClosable是由SQLiteQuery创建的SQLiteQueryDriver,我没有看到任何证据表明存在一个对象池或者在这里可以解释"新"如何SQLiteClosable已经关闭的事情.事实上它是零星的(意味着相同的UI操作有时会触发异常,但并非总是如此)表明某种池,竞争条件或某种东西......但我不知道在哪里.

思考?

谢谢!

更新:有问题的代码来自我的Android编程教程书中的LunchList教程.它有点分散,不太适合直接在SO中发布.如果您想查看它,可以从上面的链接下载该书的代码.我不记得当时学生正在编写的教程的哪个版本,尽管它在Tutorial 12-Tutorial 16范围内.我大多希望遇到一个曾经绊过这个问题的人并且有可能是罪魁祸首.我很确定我的数据库是开放的.再次感谢!

Jar*_*ard 53

这个让我疯狂的时间最长.我发现的解决方案非常简单:不要保留SQLiteDatabase对象的引用.相反,每次需要时都使用SQLiteOpenHelper并拨打电话getWritableDatabase().来自文档:

公共同步SQLiteDatabase getWritableDatabase()

创建和/或打开将用于读写的数据库.成功打开后,数据库将被缓存,因此您可以在每次需要写入数据库时​​调用此方法.

答案就在那里.

  • 嗯...这很有意思.看起来你可以在SQLiteOpenHelper上调用`close()`来关闭数据库.我将不得不尝试这个.非常感谢! (2认同)

小智 9

SQLiteDatabase在某些情况下会自动关闭.

http://darutk-oboegaki.blogspot.com/2011/03/sqlitedatabase-is-closed-automatically.html

Cursor的getCount()和onMove()方法使用SQLiteQuery触发实际查询.获得所有必需的数据后,SQLiteQuery会减少SQLiteDatabase实例的引用计数.当引用计数达到0时,数据库将关闭.

请注意,查询可以异步执行,在这种情况下,如果在SQLiteQuery完成准备数据之前调用它,则getCount()可能返回-1.