Android AsyncTask and SQLite DB Instance

I have a problem and am not sure how to approach it. Activity in my application has several AsyncTask that access a single SQLiteOpenHelper . I initialize and open the helper in onCreate() , and I close it in onStop() . I also check if it was initialized in onResume() .

Since I published my application, I got a number of errors with a Null Exception in doInBackground , where I am trying to access the DB helper. I know this happens because the DB closes ( onStop() ) just before doInBackground is doInBackground .

My question is: where should I close the database connection? Is it correct to use one instance of the database helper in Activity and access it from multiple threads ( AsyncTasks )? Or should I use a separate instance of the secondary DB for each AsyncTask ?

This is a simplified skeleton of my activity:

 public class MyActivity extends Activity{ private DbHelper mDbHelper; private ArrayList<ExampleObject> objects; @Override public void onStop(){ super.onStop(); if(mDbHelper != null){ mDbHelper.close(); mDbHelper = null; } } @Override public void onResume(){ super.onResume(); if(mDbHelper == null){ mDbHelper = new DbHelper(this); mDbHelper.open(); } } @Override public void onCreate(Bundle icicle) { super.onCreate(icicle); DbHelper mDbHelper = new DbHelper(this); mDbHelper.open(); } private class DoSomething extends AsyncTask<String, Void, Void> { @Override protected Void doInBackground(String... arg0) { objects = mDbHelper.getMyExampleObjects(); return null; } @Override protected void onPostExecute(final Void unused){ //update UI with my objects } } private class DoSomethingElse extends AsyncTask<String, Void, Void> { @Override protected Void doInBackground(String... arg0) { objects = mDbHelper.getSortedObjects(); return null; } @Override protected void onPostExecute(final Void unused){ //update UI with my objects } } } 
+8
android sqlite android-asynctask sqliteopenhelper
source share
3 answers

You mentioned that before closing the database you cancel AsyncTask. But you should keep in mind that the cancellation of AsyncTask simply signals the cancellation of the task, and you need to check isCancelled () in doInBackground () and make it necessary to stop database operations.

Before closing the database, you need to check getStatus () to make sure AsyncTask is stopped.

+1
source share

You do not need to manage the db connection for each action. You can do this in an instance of android.app.Application and db access using this instance. Something like that:

 public class MyApplication extends Application { // Synchronized because it possible to get a race condition here // if db is accessed from different threads. This synchronization can be optimized // thought I wander if it necessary public synchronized static SQLiteDatabase db() { if(self().mDbOpenHelper == null) { self().mDbOpenHelper = new MyDbOpenHelper(); } return self().mDbOpenHelper.getWritableDatabase(); } public static Context context() { return self(); } @Override public void onCreate() { super.onCreate(); mSelf = this; } private static MyApplication self() { if (self == null) throw new IllegalStateException(); return mSelf; } private MyDbOpenHelper mDbOpenHelper; private static MyApplication mSelf; } 

This way you can be sure that Db is always available.

And yes, having one instance of the Db helper is good practice. By default, synchronization is performed by default.

+11
source share

It's good to use one DB Helper . The problem is that when the user leaves the Activity , the DB closes, but AsyncTask can still work. Therefore, you should check that the DB not null when you try to access it, and if it is null , it may mean that your Activity been destroyed and cancel this task.

+5
source share

All Articles