One of my content providers manages multiple databases, the same schema with different data sets. To prevent an IllegalStateException from being skipped when the garbage collection detected that my content provider had an open database that no longer referenced it, even though SQLiteCursor left me with several options:
1) Leave the SQLiteDatabase object open and place it in the collection so that you no longer use it.
2) Leave the SQLiteDatabase object open and create a cache that will allow me to reuse the database object when accessing the same database.
3) Close the database when the cursor is closed.
Decision 1 contradicts my best judgment. A solution is another form of resource leakage; its only economic grace is that it does not violate the system. I decided this choice immediately.
Solution 2 was my idea for a better solution. It saved resources and simultaneously reduced runtime without opening a database connection. The downside of this solution was that I would have to write a cache, and that would increase the size of the application. Size really wasn't a problem, but time was written. I have passed this decision now and can return to it later.
Solution 3 is the one that decided to go. First, I thought it would be easy to do; in action, all I had to do was reset the cursor returned by my Content Provider back to SQLiteCursor. Then I could call its getDatabase () method and call close () on the database.
It's impossible. It turns out that the cursor returned by the content provider is in a wrapper class that prevents direct access to the actual Cursor object. The delegate-delegate method of the shell invokes it to be received in Cursor. There is no chance to return the cursor back to its derived type.
So, instead of blaming the closure of the database on activity, I went a different and simpler way. I got my own Cursor class by extending the SQLiteCursor class. I added two data members to my derived class; one for linking to the database, and the other an identifier for use in debugging. The ctor class had the same signature as the SQLiteCursor ctor, with an additional parameter added to the end to set the ID value. Ctor installed a database data member to ensure that something was referencing the database if garbage collection occurred before the cursor was closed.
I tried the close () method to close the cursor [super.close ()] and close the database if the link was not null.
I also overridden the toString () method so that the ID is added to the string. This allowed me to keep track of which cursors were open and which of them were open and closed in the log file.
I also added the closeForReuse () method so that the content provider can reuse the database for multiple queries without having to open a new database connection each time.
I also created a class that implemented the SQLiteDatabase.CursorFactory interface. He created my new derived cursor class and controlled the identifier value passed to each of them.
This decision still requires that each action close the cursors passed to it when they are made using the cursor. Since this is a good programming practice, this was not a problem.