I have read plenty of blogs and tutorials on how to create and use database connections when working with android. Although I have plenty of working examples, different implementations result in different issues.
Example, I use a datasource class, Datasource and a database helper class, DBManagement.
DataSource
public class DataSource {
// Database fields
private SQLiteDatabase database;
private DBManagement dbHelper;
public SMSDataSource(Context context) {
dbHelper = new DBManagement(context);
}
public void open() throws SQLException {
if(database == null){
database = dbHelper.getWritableDatabase();
}
}
public Cursor exampleCursor(long constraint){
Cursor cur = database.query(DBManagement.TABLE_NAME,
new String[] {DBManagement.Column}, "constraint="+constraint, null, null, null, null);
return cur;
}
//.. other methods down here which do rawQuery, QueryBuilder, etc..
DBManagement
public class DBManagement extends SQLiteOpenHelper{
// .. table definitions and columns etc ..//
public DBManagement(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
In my onCreate methods within activity, I will call datasource.open() and the SQL connection is open. After that I will do:
DataSource datasource = new DataSource();
Cursor cursor = datasource.exampleCursor(1);
startManagingCursor(cursor);
If I navigate to a new activity, I get the following error:
06-27 21:59:14.812: E/Database(13396): close() was never explicitly called on database '/data/data/com.example.package/databases/db.db'
If i add datasource.close(); to the end of onCreate, none of the simple cursor adapters work, or I get errors that the db is not open if perform an action on a conextual menu.
What is the best way to handle the above?
So I did the following, and I am still getting the database issue:
@Override
public void onBackPressed() {
// do something on back.
//Log.i(getClass().toString(), "onBackPressed");
datasource.close();
finish();
return;
}
@Override
protected void onResume(){
super.onResume();
onCreate(null);
}
@Override
protected void onRestart(){
datasource = new DataSource(this);
datasource.open();
filters = datasource.getFilterCursor();
startManagingCursor(filters);
super.onRestart();
}
@Override
protected void onPause(){
//Log.i(getClass().toString(), "onPause");
((CursorAdapter) adapter).getCursor().close();
datasource.close();
super.onPause();
}
@Override
protected void onStop(){
//Log.i(getClass().toString(), "onStop");
datasource.close();
super.onStop();
}
My Datasource.java class has the following:
public Datasource(Context context){
dbHelper = new DBManagement(context);
}
public void open() throws SQLException {
if( database == null ){
database = dbHelper.getWritableDatabase();
}
}
public void close(){
if(dbHelper != null){
dbHelper.close();
}
}
This is actually very simple:
finally), etc.startManagingCursor()close()on the database helper. I will be automatically closed when your process dies.Additionally: frequent opening and closing is definitely a bad idea, since it carries quite a lot of overhead.
Using loaders is also an option. You definitely don’t need to use a content provider to use a loader however it is not as straightforward as it could be. Using an content provider involves IPC which is usually overkill if you don’t plan to export your data to other apps.