Feeds:
Posts
Comments

Archive for March, 2010

There’s a lot of questions about how to correctly manage databases in your Activity but very few answers. If you get leak error “SQLiteDatabase created and never closed” you have this problem. Even the Google Notepad tutorial many people use as a starting point is leaving open databases. This is what I’ve found out, but I’m no expert:

I use a global variable as the database adapter I’ve created and I want to use this in numerous methods inside the activity to read/update/save data from the Activity to the database. Opening and closing the database in each method isn’t a good idea, even worse is creating an adapter each time you need to access the database so.

A database should be instantiated in the onCreate. This ensures that we only have only one when the Activity is paused and resumed and that we don’t have to create a new on each resume.

public class ListEntry extends ListActivity {
private NotesDbAdapter mDbHelper;

/** Called when the activity is first created. */
 @Override
 public void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
   setContentView(R.layout.listentry_main);

   mDbHelper = new NotesDbAdapter(this);

   registerForContextMenu(getListView());
 }

Filler functions should not be called in the onCreate, because when an Activity is created. onResume is also called after onCreate. So to be able to have the correct behavior when the Activity is just paused and resumed the open-statement should be there. This “incorrect” behavior can be seen in the Notepad Tutorial V3 (NoteEdit.java, onCreate) which calls populateFields twice when the Activity is created (first onCreate, then onResume).

 @Override
 protected void onResume() {
 super.onResume();
 mDbHelper.open();
 fillData();            // function that populates the view with values from the database
 }

onPause should close the database so that it frees up resources for other Activities. This is also called when the Activity is destroyed or finished so there’s no need to close the database “onFinish” or “onDestroy”. Closing of the database is not present in the NotePad tutorial and will create Leaks when NoteEdit tries to open an already open database when started again.

@Override
 protected void onPause() {
   super.onPause();
   Log.d("ListEntry onResume db.close()", "close");
   mDbHelper.close();
 }

Functions that create intents to start other Actives should not do anything with the database this is already handled with onPause. For example:

 @Override
 protected void onListItemClick(ListView l, View v, int position, long id) {
   super.onListItemClick(l, v, position, id);

   Intent i = new Intent(this, AddEntry_Tabbed.class);
   startActivityForResult(i, ACTIVITY_EDIT);
 }

Functions that gets called when the Activity is called should not try to open the database and use fillData. This is already taken care of in onResume which also in called when a result is returned from another Activity. For example:


 // Callback when you get back from "StartActivityForResult"
 @Override
 protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
   super.onActivityResult(requestCode, resultCode, intent);
   // Do something.
 }

Read Full Post »