exception:尝试获取closuresSQLiteClosable的引用

5月份,我在[android-developers] Google Group上发布了这个消息 。 我从来没有听到,直到我的一个学生上周做了,才能够重现这个问题。 我想我会把它张贴在这里,看看它是否响了任何人的钟声。

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

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

当我运行它,零星地,我得到这个:

 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) 

这对我来说没有意义。 数据库肯定是开放的。 SQLiteClosable是由SQLiteQuery创build的SQLiteQueryDriver ,我没有看到有证据表明存在一个对象池,或者在这里可以解释“新” SQLiteClosable是如何closures的。 事实上,它是零星的(意味着相同的用户界面操作有时触发exception,但并不总是)暗示某种forms的游泳池,竞争条件或某事…但我不知道在哪里。

思考?

谢谢!

更新 :有问题的代码是从我的Android编程教程书的LunchList教程。 它有点分散,不太适合直接在SO中发布。 你可以从上面的链接下载该书的代码,如果你想看看它。 我不记得那个时候学生正在编写哪个教程的版本,虽然它在教程12-Tutorial 16范围内。 我主要希望碰到一个曾经绊倒这个问题的人,并有可能的罪魁祸首。 我很确定我的数据库是打开的。 再次感谢!

这一个让我疯狂了最长的时间。 我发现的解决scheme非常简单:不要保留对SQLiteDatabase对象的引用。 相反,使用SQLiteOpenHelper并在每次需要时调用getWritableDatabase() 。 从文档:

公共同步SQLiteDatabase getWritableDatabase()

创build和/或打开将用于读取和写入的数据库。 一旦成功打开,数据库就会被caching,所以您可以在每次需要写入数据库时​​调用此方法。

答案是一直在那里。

在某些情况下,SQLiteDatabase会自动closures。

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

Cursor的getCount()和onMove()方法使用SQLiteQuery触发一个实际的查询。 在获得所有必需的数据之后,SQLiteQuery将减lessSQLiteDatabase实例的引用计数。 当引用计数达到0时,数据库closures。

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

我有几天相同的问题,我的解决scheme是在数据库操作后,我的查询和close()方法之前放置open()方法。 看起来像这样

 open(); Cursor cur=db.query(DATABASE_TABLE_CON, null, null, null, null, null, " name ASC"); close(); return cur; 

它工作得很好,但是我担心资源成本。 在进行任何操作之前,我不确定是否在开放和closures数据库上花费了更多的资源。

尽pipe已经遵循了Jarett的build议 ,但我也遇到过类似的问题。 就我而言,这个问题在定位方面的变化是相当有规律的。 我发现,由于某种原因,我还没有到底,我的代码生成两个相同的,几乎同时AsyncTasks方向的变化(而不是只有一个,当活动正常开始)。 这些任务同时从不同的线程执行相同的数据库查询。

这个exception(偶尔还有一些SQLiteException)是结果。 所以这个消息似乎是并发问题的症状,即使它不一定是这里发布的原始问题的根源。