{"id":691,"date":"2010-12-16T18:20:10","date_gmt":"2010-12-16T23:20:10","guid":{"rendered":"http:\/\/www.outofwhatbox.com\/blog\/?p=691"},"modified":"2011-01-11T15:49:26","modified_gmt":"2011-01-11T20:49:26","slug":"android-closing-those-database-objects","status":"publish","type":"post","link":"https:\/\/www.outofwhatbox.com\/blog\/2010\/12\/android-closing-those-database-objects\/","title":{"rendered":"Android: Closing those database objects"},"content":{"rendered":"<div style=\"font-size:1.5em\"><em><strong>(Or, what the Notepad tutorial never told you.<\/strong><\/em>)<\/div>\n<p>If you&#8217;ve used Android&#8217;s <a href=\"http:\/\/developer.android.com\/resources\/tutorials\/notepad\/index.html\">Notepad<\/a> tutorial (Version 3) , or modeled your own Activity on <a href=\"http:\/\/developer.android.com\/resources\/tutorials\/notepad\/notepad-ex3.html\">Notepadv3<\/a>, then you&#8217;ve probably seen log messages that look something like this:<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nandroid.database.sqlite.DatabaseObjectNotClosedException: \r\n    Application did not close the cursor or database object that was opened here\r\nat android.database.sqlite.SQLiteCompiledSql.&lt;init&gt;(SQLiteCompiledSql.java:62)\r\nat android.database.sqlite.SQLiteProgram.&lt;init&gt;(SQLiteProgram.java:80)\r\nat android.database.sqlite.SQLiteStatement.&lt;init&gt;(SQLiteStatement.java:36)\r\nat android.database.sqlite.SQLiteDatabase.compileStatement(SQLiteDatabase.java:1145)\r\nat android.database.sqlite.SQLiteDatabase.updateWithOnConflict(SQLiteDatabase.java:1671)\r\nat android.database.sqlite.SQLiteDatabase.update(SQLiteDatabase.java:1622)\r\nat com.android.demo.notepad3.NotesDbAdapter.updateNote(NotesDbAdapter.java:186)\r\nat com.android.demo.notepad3.NoteEdit.saveState(NoteEdit.java:106)\r\nat com.android.demo.notepad3.NoteEdit.onPause(NoteEdit.java:87)\r\nat android.app.Activity.performPause(Activity.java:3842)\r\nat android.app.Instrumentation.callActivityOnPause(Instrumentation.java:1190)\r\nat android.app.ActivityThread.performPauseActivity(ActivityThread.java:3335)\r\nat android.app.ActivityThread.performPauseActivity(ActivityThread.java:3305)\r\nat android.app.ActivityThread.handlePauseActivity(ActivityThread.java:3288)\r\nat android.app.ActivityThread.access$2500(ActivityThread.java:125)\r\nat android.app.ActivityThread$H.handleMessage(ActivityThread.java:2044)\r\nat android.os.Handler.dispatchMessage(Handler.java:99)\r\nat android.os.Looper.loop(Looper.java:123)\r\nat android.app.ActivityThread.main(ActivityThread.java:4627)\r\nat java.lang.reflect.Method.invokeNative(Native Method)\r\nat java.lang.reflect.Method.invoke(Method.java:521)\r\nat com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)\r\nat com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)\r\nat dalvik.system.NativeStart.main(Native Method)\r\n<\/pre>\n<p>This is resolved easily enough by overriding the <a href=\"http:\/\/developer.android.com\/reference\/android\/app\/Activity.html#onDestroy%28%29\"><code>onDestroy<\/code><\/a> method in each of the Activities in your application \u00e2\u20ac\u201d or at least, each Activity that uses the database. In the Notepadv3 app, this means overriding <code>onDestroy<\/code> in both the Notepadv3 and NoteEdit classes. The same definition is suitable for both classes:<\/p>\n<pre class=\"brush: java; title: onDestroy; notranslate\" title=\"onDestroy\">\r\n    public void onDestroy() {\r\n        super.onDestroy();\r\n\r\n        \/\/ Replace mDbHelper as needed with your database connection, or\r\n        \/\/ whatever wraps your database connection. (See below.)\r\n        mDbHelper.close();\r\n    }\r\n<\/pre>\n<p>In the Notepadv3 tutorial, the <code>mDbHelper<\/code> field is an instance of the class <code>NotesDbAdapter<\/code>, which wraps the database connection. <code>NotesDbAdapter<\/code> comes from google with the <code>close<\/code> method already defined, but there&#8217;s no code that calls it. With this change, we&#8217;re supplying the code that calls <code>close<\/code> at the right time. (<em>I think.<\/em>)<\/p>\n<p>In general: If your activity opens a database by calling either <a href=\"http:\/\/developer.android.com\/reference\/android\/database\/sqlite\/SQLiteOpenHelper.html#getReadableDatabase%28%29\"><code>SQLiteOpenHelper.getReadableDatabase<\/code><\/a> or <a href=\"http:\/\/developer.android.com\/reference\/android\/database\/sqlite\/SQLiteOpenHelper.html#getWritableDatabase%28%29\"><code>SQLiteOpenHelper.getWritableDatabase<\/code><\/a>, then you should rely on <a href=\"http:\/\/developer.android.com\/reference\/android\/database\/sqlite\/SQLiteOpenHelper.html#close%28%29\"><code>SQLiteOpenHelper.close<\/code> <\/a>to close that database. Your activity&#8217;s <code>onDestroy<\/code> method must result in a call to the <code>close<\/code> method for any instances of <code>SQLiteOpenHelper<\/code>, or classes derived from it, that you&#8217;ve created. (In the code above, <code>mDbHelper.close<\/code> will have that effect.) <code>SQLiteOpenHelper.close<\/code> will then close any database handle that it created for you.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Android applications based on the Notepadv3 tutorial are prone to a DatabaseObjectNotClosedException when they&#8217;re closed. Here&#8217;s how to prevent them.<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[33],"tags":[51,47,46,45],"_links":{"self":[{"href":"https:\/\/www.outofwhatbox.com\/blog\/wp-json\/wp\/v2\/posts\/691"}],"collection":[{"href":"https:\/\/www.outofwhatbox.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.outofwhatbox.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.outofwhatbox.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.outofwhatbox.com\/blog\/wp-json\/wp\/v2\/comments?post=691"}],"version-history":[{"count":7,"href":"https:\/\/www.outofwhatbox.com\/blog\/wp-json\/wp\/v2\/posts\/691\/revisions"}],"predecessor-version":[{"id":693,"href":"https:\/\/www.outofwhatbox.com\/blog\/wp-json\/wp\/v2\/posts\/691\/revisions\/693"}],"wp:attachment":[{"href":"https:\/\/www.outofwhatbox.com\/blog\/wp-json\/wp\/v2\/media?parent=691"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.outofwhatbox.com\/blog\/wp-json\/wp\/v2\/categories?post=691"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.outofwhatbox.com\/blog\/wp-json\/wp\/v2\/tags?post=691"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}