Monday, May 16, 2011

Cleaning up a "database not closed" error

I kept getting this really annoying exception in logcat:

"android.database.sqlite.DatabaseObjectNotClosedException: Application did not close the cursor or database object that was opened here"

I tried to resolve it, by closing the database at various points in the test, but nothing worked - unless I closed it immediately, in which case nothing else worked. Luckily, a google search revealed that you need to check for null before opening the database. So, I change this code:

myDataBase = SQLiteDatabase.openDatabase(myPath, null,
SQLiteDatabase.OPEN_READONLY);

To this:

if (null == myDataBase){

myDataBase = SQLiteDatabase.openDatabase(myPath, null,
SQLiteDatabase.OPEN_READONLY);
}


And now it seems to be working ok - as long is I explicitly close the database in the test! I was doing that before, but not on all of them - the extra opens must have been part of the problem.

Another interesting oddity in exploring this exception had to do with the famed ActivityInstrumentationTestCase2 test class. Whenever I created the database helper as class member, I was unable access it from the teardown method. By checking the source code at:

http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/2.2_r1.1/android/test/ActivityUnitTestCase.java (where's the 2?)

I saw that there was a method in the teardown called scrubClass with this code:

// Scrub out members - protects against memory leaks in the case where someone
// creates a non-static inner class (thus referencing the test case) and gives it to
// someone else to hold onto
scrubClass(ActivityInstrumentationTestCase.class);

This method, inherited from test case, actually takes the class and uses reflection to delete it's members - no wonder I got a null pointer exception!

No comments:

Post a Comment