Android database error : close() was never explicitly called on database


ERROR/Database:close() was never explicitly called on database

This was the error,which continuously decorated my LOGCAT as I bounce to and fro between activities.And to my agony, I had closed all the opened database on activity onDestroy() method and opened the same database on activity onCreate() method.
Before moving further,I would like to show how I was implementing it

  1. I have DatabaseHelper class extending SQLiteOpenHelper
  2. And DatabaseManager class managing all the database related actions


public class DatabaseHelper extends SQLiteOpenHelper {
public DatabaseHelper(Context context) {
super(context, DB_NAME, null, DB_VERSION);
}

@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(CREATE_CATEGORY_TABLE);
}

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS "+ CATEGORY_TABLE_NAME);
onCreate(db);
}
}



public class DatabaseManager {
private SQLiteDatabase db;

public DatabaseManager(Context context) {
DatabaseHelper dbHelper = new DatabaseHelper(context);
this.db = dbHelper.getWritableDatabase();
}

public void closeDatabase() {
db.close();
}
}


And on any activity I would implement database close and open like this

public class MainActivity extends Activity{
private DatabaseManager dbManager;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.firstpage_layout);
dbManager = new DatabaseManager(getApplicationContext());
}

@Override
protected void onDestroy() {
super.onDestroy();
if(dbManager != null)dbManager.closeDatabase();
}
}


But when I navigate from one activity to another,if I have to close the previously opened database ,I have to finish() the previous activity,and then only onDestroy() will be called.And my previously opened database will be closed and I can open the same database on another activity without any LOGCAT errors.

BUT,if I navigate to another activity,without finishing my previous activity,then onDestroy() method of previous activity won’t be called.Then,on next activity onCreate() method ,if I try to open the same database via

dbManager = new DatabaseManager(getApplicationContext());

LOGCAT will show error on DatabaseManager class

this.db = dbHelper.getWritableDatabase();


So,instead on closing database on activity onDestroy() method and opening database on activityonCreate(); close database on activity onPause()method and open database on activityonResume() method.


@Override
protected void onPause() {
super.onPause();
if(dbManager != null)dbManager.closeDatabase();
}

@Override
protected void onResume() {
super.onResume();
dbManager = new DatabaseManager(getAppicationContext());
}


But while browsing on StackOverflow answers I found two verdicts on this,some say it is unwise to close and open database repeatedly and state that open database only once and do all those database related actions.While,the other verdict opposes this and says that opening database for prolonged time is not a good practice. Frankly speaking,I couldn’t test which verdict is right and any of you readers able to clarify me these two verdicts,I will be glad.

Further as per the first verdict i.e. if you want to open database only once,then you can make DatabaseManager a singleton one like this

public enum DatabaseManager {
INSTANCE;
private SQLiteDatabase db;
private boolean isDbClosed =true;

public void init(Context context) {
DatabaseHelper dbHelper = new DatabaseHelper(context);
if(isDbClosed){
isDbClosed =false;
this.db = dbHelper.getWritableDatabase();
}

}


public boolean isDatabaseClosed(){
return isDbClosed;
}

public void closeDatabase(){
if(!isDbClosed && db != null){
isDbClosed =true;
db.close();
}
}

And access this class on any activity via

public class MainActivity extends Activity{
private DatabaseManager dbManager;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.firstpage_layout);
dbManager = DatabaseManager.INSTANCE;
dbManager.init(this);
}
}

When you do this,there will be only one open database in your entire application and the LOGCAT error won’t be shown. I simply can’t decide which verdict to choose from,open database for entire application life or to close and open database on each activity.Any one implementation makes your application get rid of close()
was never explicitly called on database
error.But if you want to close() and open() database on activity resume() and pause() using singleton class ,you can do like this


@Override
protected void onResume() {
super.onResume();
if(dbManager == null){
dbManager = DatabaseManager.INSTANCE;
dbManager.init(this);
}else if(dbManager.isDatabaseClosed()){
dbManager.init(this);
}
}

@Override
protected void onPause() {
super.onPause();
if(!dbManager.isDatabaseClosed())
dbManager.closeDatabase();
}

And if you find out among two :

a) open database on entire application

b) or close and open database on activity resume and pause

which is the best option, do give me some insight on my blog comment, CHEERS 😉

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s