Tenfour04
Tenfour04

Reputation: 93902

Is it essential to close the database?

In Google's Notepad Example, they don't seem to close the database, at least not in onDestroy().

What is the purpose of closing it, and do I really need to? Does an open database take up significant memory? I have found that closing it in onDestroy leaves vulnerabilities if there are any threads running that might try to access it after the Activity is finished.

Upvotes: 12

Views: 6379

Answers (2)

Farray
Farray

Reputation: 8548

If you don't close the database connections, they'll cause memory leaks over time.

The Notepad example does use startManagingCursor, but you still need to explicitly close the db connection. Run the Notepad example as-is and edit several notes in succession, you'll see that it starts throwing Warnings and Errors in LogCat. (In larger applications, you'll also start to see Memory Leak Detection warnings.)

W/SQLiteCompiledSql(  302): Releasing statement in a finalizer. Please ensure that you explicitly call close() on your cursor: INSERT INTO notes(body, title) VALUES(?, ?);
W/SQLiteCompiledSql(  302): android.database.sqlite.DatabaseObjectNotClosedException: Application did not close the cursor or database object that was opened here
W/SQLiteCompiledSql(  302):     at android.database.sqlite.SQLiteCompiledSql.<init>(SQLiteCompiledSql.java:62)
...
W/SQLiteCompiledSql(  302):     at dalvik.system.NativeStart.main(Native Method)
E/Database(  302): close() was never explicitly called on database '/data/data/com.android.demo.notepad3/databases/data' 
E/Database(  302): android.database.sqlite.DatabaseObjectNotClosedException: Application did not close the cursor or database object that was opened here
E/Database(  302):  at android.database.sqlite.SQLiteDatabase.<init>(SQLiteDatabase.java:1810)
...
E/Database(  302):  at dalvik.system.NativeStart.main(Native Method)

You mentioned that closing it in onDestroy() "leaves vulnerabilities" in any non-UI threads that are still running. If you're using AsyncTask, you can check the status of of these threads using getStatus on your tasks.

if ( myAsyncTask.getStatus() == AsyncTask.Status.FINISHED ){
    mDbHelper.close();
}

Then close the connection in the onPostExecute method of your AsyncTask.

Hope that helps...

Upvotes: 10

Macarse
Macarse

Reputation: 93173

You should close it.

The notepad example should be using Activity's startManagingCursor.

Upvotes: 0

Related Questions