2

I wondering where and when I should open/close my SQLiteDatabase connection in my AsyncTaskLoader. I don't feel like i fully understand the lifecycle of a Loader, so I'm afraid that I might run into some memory leaks/NullPointerExceptions if I don't to this right. I currently open up my SQLiteDatabase in the constructor of my loader:

private class SQLiteCursorLoader extends AsyncTaskLoader<Cursor> {

    private String _queryString;
    private SQLiteDatabase _db;
    ...

    public SQLiteCursorLoader(Context context, String queryString) {
        super(context);
        _queryString = queryString;
        _db = MySQLiteOpenHelper.getWritableDatabase();
    }

    ....

}

But where do I close the connection again?

soren.qvist
  • 7,376
  • 14
  • 62
  • 91

1 Answers1

2

The best way would probably be to take a copy of CursorLoader.java and modify the loadInBackground() method to use your SQLiteDatabase

/* Runs on a worker thread */
@Override
public Cursor loadInBackground() {
    Cursor cursor = // Your stuff goes here <..>
    if (cursor != null) {
        // Ensure the cursor window is filled
        cursor.getCount();
        registerContentObserver(cursor, mObserver);
    }
    return cursor;
}
Jens
  • 16,853
  • 4
  • 55
  • 52
  • So I should open the DB, grab my Cursor and then close the DB all in loadInBackground()? – soren.qvist Mar 03 '12 at 14:40
  • 1
    You shouldn't be closing your SQLiteDatabase instance at all. A ContentProvider typically never does this. If you have a clear point where you're destroying the resources of all Activity:s and Services that are using the SQLite database you should close the db and, most importantly, the **SQLiteOpenHelper** instance. – Jens Mar 03 '12 at 14:57
  • So if I'm using a SQLiteOpenHelper to open my database, it will automatically tie itself to the activity lifecycle? – soren.qvist Mar 03 '12 at 14:58
  • No it will not - but note - the SQLiteOpenHelper is not something you should create multiple instances of (that will end badly in most cases) - are you using the database in *more* than one activity? – Jens Mar 03 '12 at 15:10
  • Yes, or rather, I have multiple fragments that use the database, and those fragments belong to different activities – soren.qvist Mar 03 '12 at 15:40
  • 1
    Then your SQLiteOpenHelper should typically be a singleton - and never #closed. Cursors and stuff like that should of course be closed. – Jens Mar 03 '12 at 15:49
  • Thanks for that tip! I'll look into the singleton pattern. – soren.qvist Mar 03 '12 at 16:14
  • Just to be clear here - do you (or does Diane) really mean make a copy or would subclassing CursorLoader and overriding the loadInBackground work just as well? – Mick Jan 04 '13 at 11:10
  • Having dug into this a little more I think there are pros and cons to both subclassing and to copying. Overall the AsynchTaskLoader class appears to be quite complex with plenty of potential pitfalls and it might be good to build on a well know example. The SQLiteCursorLoader example at the following link is not at '1.0' release yet but given the pedigree I am guessing it will be well used and tested - maybe someone can comment who has used it (scroll down to see documentation/explanation):https://github.com/commonsguy/cwac-loaderex – Mick Jan 04 '13 at 17:16