16

Can two or more Android Activities open an sqlite3 database for write?

I have two Activities that need to insert data into the same sqlite database. When the second Activity calls SQLiteOpenHelper.getWriteableDatabase() an IllegalStateException is thrown with the message "SQLiteDatabase created and never closed".

I've been able to avoid the Exception by making my database object a singleton but I'm thinking there must be a better way.

Thanks,

John

4
  • You could close the db after you wrote to it.. Commented Oct 12, 2009 at 21:11
  • I thought about that as well, but one activity is a ListActivity that is populated using a Cursor adapter. I thought that closing the database would make the adapter's requery fail. Commented Oct 12, 2009 at 21:19
  • @John: if you use singleton database, where do you open and close it? Commented Aug 17, 2011 at 18:50
  • When needed it I open the db, do whatever, then close it. Commented Aug 19, 2011 at 14:48

3 Answers 3

13

There's never really more than one Activity running at a time. The easy way to fix this would be to have the first Activity close it's connection before starting the second Activity. You can do this in the onPause() then reopen it in the onResume(). Something like this (very psuedo-code):

MyActivity {
    OnResume()
        open connection to database
    OnPause()
        close connection to database
}

This way you're never trying to have more than one connection at a time and the connection is always available.

Sign up to request clarification or add additional context in comments.

9 Comments

I've been wondering if this approach is better than having the activities use the same singleton object. I think it is because this approach leaves the connection is the right state when pausing an activity. Having a singleton connection makes for problematic cleanup. Thanks.
Yeah... if you aren't closing it in onPause then the connection just gets left there dangling if (for instance) you get a phone call.
This does not work. I am getting an InvalidStateException and a SQL query that failed to execute, even before onResume() is invoked. Android seems to be requerying cursors prior to calling onResume().
I'm successfully using this pattern in half a dozen apps. If you're having issues with it you must be doing something funny. Ask a question and post code.
@peno: So, you're saying that my suggestion to solve a particular problem won't solve a completely different problem? Imagine that.
|
2

I also have multiple Activities and each Activity opens its own database connection. I keep the main Activity alive while I start other activities, and I call finish() on the child activities when I no longer need them.

What I am seeing is that a child Activity can successfully open a connection and query data while the main Actitity is still holding on to its DBAdapter. When the child Activity ends, the main Activity requeries any cursors that are open. This seems to happen automatically.

However, after clicking around on the user interface for a while, which causes my app to start and finish Activities, I will eventually get the exception:

ERROR/Database(17657): Leak found
ERROR/Database(17657): java.lang.IllegalStateException:
      /data/data/yourpackage/databases/yourdatabase 
      SQLiteDatabase created and never closed
ERROR/Database(17657): at android.database.sqlite.SQLiteDatabase.<init>
     (SQLiteDatabase.java:1694)

The exception is not from the Activity that is currently in the foreground, but from one that was finished a while ago. So, what happens is that the garbage collector is cleaning up and finding the open database connection. This does not affect the app - it continues to work fine and all queries from the foreground Activity return data.

The solution is simply to close the connection in the child Activity. The onDestroy() event is the right place to do that:

@Override    
protected void onDestroy() {        
    super.onDestroy();
    myAdapter.close();
}

Since I put this in all my child Activities, I no longer get the exception.

Comments

0

What I would do is define the database in a superclass which is AppCompatActivity if all the activities extend this class, or define it in Activity class which is inherited for all activities.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.