Reputation: 4930
I've made an application that uses a downloaded SQLite database. To retrieve data in it I'm using a ContentProvider
. When I need to read the database, I always (I've checked at least five times) use a code like this:
Cursor c = getContext().getContentResolver().query(MyContentProvider.ITEMSURI,
projection,where,null,null);
if(c.moveToFirst()){
while(!c.isAfterLast()){
itemsList.add(cursorToItem(c));
c.moveToNext();
}
}
if(c!=null) c.close();
But I keep getting many errors like this (I make a sequence of queries in a for loop):
10-18 13:16:01.709: W/SQLiteConnectionPool(27704): A SQLiteConnection object
for database '/storage/emulated/0/MyAPP/mydb.sqlite' was leaked!
Please fix your application to end transactions in progress properly and to
close the database when it is no longer needed.
What could cause all these warnings? Cursor is always closed and in ContentProvider
there's no need to close database.
Code:
This is the class that manages the database:
public class OpenMyDBHelper{
private static final String DB_NAME = "mydb.sqlite";
private static final File DB_PATH = new File(
MyAppFolderManager.getInternalMemoryFolder(), DB_NAME);
private SQLiteDatabase db;
public SQLiteDatabase open() {
db = SQLiteDatabase.openDatabase(DB_PATH.getAbsolutePath(), null,
SQLiteDatabase.OPEN_READONLY);
return db;
}
public void close() {
db.close();
}
}
And this is my ContentProvider
subclass:
public class MyContentProvider extends ContentProvider {
private OpenMyDBHelper db;
//static paths/Uri definitions....
private final static int ITEMS = 1;
private static final UriMatcher sURIMatcher = new UriMatcher(
UriMatcher.NO_MATCH);
static {
sURIMatcher.addURI(AUTHORITY, ITEMS_PATH, ITEMS);
}
@Override
public boolean onCreate() {
db = new OpenMyDBHelper();
return false;
}
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
Cursor cursor = null;
SQLiteDatabase database = db.open();
int uriType = sURIMatcher.match(uri);
switch (uriType) {
case ITEMS:
cursor = database.query(Constants.TABLE_ITEMS,
projection, selection, selectionArgs, null,null,
null);
cursor.setNotificationUri(getContext().getContentResolver(), ITEMSURI);
break;
default:
throw new IllegalArgumentException("Unknown URI (" + uri + ")");
}
return cursor;
}
@Override
public String getType(Uri uri) {
return null;
}
//It's just a read-only db, I don't need the CUD operations...
@Override
public Uri insert(Uri uri, ContentValues values) {
return null;
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
return 0;
}
@Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
return 0;
}
}
Upvotes: 1
Views: 4672
Reputation: 9296
If you have to use getReadableDatabase many times:
You can use this.close to close your database from leak. Example :
public String getAdditionalInfo(final int id) {
yourDB = this.getReadableDatabase();
Cursor cursor = yourDB.rawQuery(selectQuery, null);
if (cursor.moveToFirst()) {
return cursor.getString(0);
}
cursor.close();
this.close();// You add this line
return "";
}
Upvotes: 1
Reputation: 1007349
What could cause all these warnings?
The fact that you keep re-opening the database. Open the database once, in onCreate()
, not on every query()
call.
Though, in all honesty, if you are not implementing the full CRUD operations, I'd just dump the ContentProvider
, as you are gaining nothing by it. It might also allow you to avoid doing a bunch of query()
calls in a loop and significantly improve performance, by using IN
operators and such in a SQLite query.
Upvotes: 3