tags:

views:

1598

answers:

4

I posted this back in May on the [android-developers] Google Group. I never heard back and was not able to reproduce the problem until one of my students did last week. I figured I'd post it here and see if it rang any bells for anyone.

In one of my code samples, I have the following method:

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

}

When I run it, sporadically, I get this:

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)

This makes no sense to me. The database is definitely open. The SQLiteClosable is the SQLiteQuery created by SQLiteQueryDriver, and I see no evidence that there is an object pool or something going on here that might explain how a "new" SQLiteClosable is already closed. The fact that it is sporadic (meaning the same UI operations sometimes trigger the exception, but not always) suggests some sort of pool, race condition, or something...but I'm not sure where.

Thoughts?

Thanks!

UPDATE: The code in question is from the LunchList tutorials out of my Android Programming Tutorials book. It's a bit spread out and not terribly suitable for posting directly in SO. You can download the code for that book from the above link if you want to take a look at it. I do not recall exactly which edition of the tutorial the student was working on at the time, though it was in the Tutorial 12-Tutorial 16 range. I was mostly hoping to run across somebody who had tripped over this problem before and had a likely culprit. I'm fairly certain my database is open. Thanks again!

+3  A: 

Mark,

Did not have much time to spend on this, but I did have a small point to make - your SQLiteClosable is likely not a SQLiteQuery object, but rather your SQLiteDatabase. If you look in the SQLiteProgram docs, then you can see that line 56 is calling acquireReference() on your database. It seems that your database is either closed, or was never opened?

HTH, and if I have some more time I might keep digging.

Thanks, Hamy

PS - Could you perhaps post some more of the code here? I think that might help

Hamy
A: 

I had same problem for a few days, and my solution was to put open() method just before my query and close() method after database operation. It looks something like this.

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

It works just fine, but I'm concerned for resources cost. I'm not sure am I spending more resources with all this opening and closing database before any action.

cikabole
+8  A: 

This one drove me insane for the longest time. The solution I have found is fairly simple: don't keep references to SQLiteDatabase objects. Instead, use a SQLiteOpenHelper and call getWritableDatabase() every time you need one. From the docs:

public synchronized SQLiteDatabase getWritableDatabase()

Create and/or open a database that will be used for reading and writing. Once opened successfully, the database is cached, so you can call this method every time you need to write to the database.

The answer was right there the whole time.

Jarett
Hmmmm...that's very interesting. It also looks like you can call `close()` on the SQLiteOpenHelper to close the database. I'll have to experiment with this. Many thanks!
CommonsWare
You're very welcome! Thank you for asking the question; it helped me to figure out the solution.
Jarett
Couldn't quite get it. Can you post a more elaborate example?
Codevalley
A: 

I've been experiencing a similar problem, despite already following Jarett's advice. In my case the problem is happening fairly regularly on orientation changes. I've discovered that, for some reason I haven't yet got to the bottom of, my code generates two identical, pretty much simultaneous AsyncTasks on an orientation change (as opposed to just one when the activity starts normally). These tasks perform the same database query at the same time from different threads.

This exception (or occasionally some other SQLiteException) is the result. So it seems that this message can be a symptom of concurrency problems, even if it is not necessarily the root of the original problem posted here.

Dan Dyer