Skip to content
Advertisement

Android and SQLite: “nested” getReadableDatabase

In my Android app I use the following code to access db:

public class DbHelper extends SQLiteOpenHelper {
/* ... */
}

public class DbManager {

    private DbHelper helper = null;

    public DbManager(Context context) {
        helper = new DbHelper(context);
    }

    public void method1(bool cond) {
        SQLiteDatabase db = helper.getReadableDatabase();

        /* operate on db... */

        if (cond) method2();

        /* operate on db... */

        db.close();
    }

    public void method2() {
        /* see below */
    }

}

method1 and method2 can be called independently from outside the class. In addition, there are situations where method1 must call method2.

In method2 I need a db instance, so I should call SQLiteDatabase db = helper.getReadableDatabase();. This is ok if method2 is not called by method1. On the other hand, if I call it from method1, I create a db handle twice.

Is this ok?

I think I can avoid this situation this way:

public void method2(SQLiteDatabase db) {

    SQLiteDatabase locDb;

    if (db == null) {
        locDb = helper.getReadableDatabase();
    } else {
        locDb = db;
    }

    /* ... */

    if (db == null) locDb.close();
}

then in method1 I will use method2(db); while from outside I will use method2(null);

Does it all make sense? Or I should simply ignore the fact that i’m creating “nested” db instances? How does this impact on performances with higher “nesting” levels?

Advertisement

Answer

The biggest issue is probably closing the database, it is inefficient to unnecessarily close and open the database.

All you need to do is get the database (getReadableDatabase or getWritableDatabase (both will under most circumstances return a writable database)). It will returns the same object, unless the database has been closed, when it then goes though the process of opening the database.

However, perhaps consider :-

public class DbManager {

   private DbHelper helper = null;
   private SQLiteDatabase db = null; //<<<<< ADDED

   public DbManager(Context context) {
      helper = new DbHelper(context);
      db = helper.getWritableDatabase(); //<<<<< ADDED
   }

   public void method1(boolean cond) {

      /* operate on db... */

      if (cond) method2();

      /* operate on db... */
   }

   public void method2() {
      /* operate on db... */
      
   }
}

Of course you may wish to also consider using a singleton approach to the DbHelper, then multiple DbManager instances, would only have the single DbHelper instance

e.g. you could have something like :-

public class DbHelper extends SQLiteOpenHelper {

   private static final String DATABASE_NAME = "whatever";
   private static final int DATABASE_VERSION = 1;
   /* ... */

   /* don't allow construction of a DbHelper by making the constructor private */
   private DbHelper(Context context) {
      super(context,DATABASE_NAME,null,DATABASE_VERSION);
   }

   volatile static private DbHelper instance = null;
   public static DbHelper getInstance(Context context) {
      if (instance == null) {
         instance = new DbHelper(context);
      }
      return instance;
   }


   @Override
   public void onCreate(SQLiteDatabase sqLiteDatabase) {

   }

   @Override
   public void onUpgrade(SQLiteDatabase sqLiteDatabase, int oldVersion, int newVersion) {

   }
}

along with

public class DbManager {

   private DbHelper helper = null;
   private SQLiteDatabase db = null;

   public DbManager(Context context) {
      helper = DbHelper.getInstance(context);
      db = helper.getWritableDatabase();
   }

   public void method1(boolean cond) {

      /* operate on db... */

      if (cond) method2();

      /* operate on db... */
   }

   public void method2() {
      /* see below */

   }
}
3 People found this is helpful
Advertisement