Вам необходимо либо закрыть объект базы данных, либо удерживать объект базы данных, чтобы в вашем поставщике контента была переменная, ссылающаяся на объект базы данных, позволяющая при сборке мусора игнорировать открытую базу данных.
Проблема с закрытием базы данных в поставщике контента заключается в том, что курсор, возвращаемый к действию, которое запросило запрос, становится пустым курсором.
Таким образом, выбор заключается в том, чтобы либо навсегда удерживать открытый объект базы данных (время жизни провайдера контента), либо убедиться, что база данных закрыта, когда курсор закрыт.
Я выбрал второй вариант и получил курсор, расширив класс SQLiteCursor и реализовав интерфейс SQLiteDatabase.CursorFactory со следующим кодом:
public class MyCursor extends SQLiteCursor
{
final SQLiteDatabase mDatabase;
final int mID;
public MyCursor(SQLiteDatabase database,
SQLiteCursorDriver driver,
String table,
SQLiteQuery query,
int cursorID)
{
super(database, driver, table, query);
mDatabase = database;
mID = cursorID;
}
/**
* Closes the database used to generate the cursor when the
* cursor is closed. Hopefully, plugging the GC Leak detected
* when using pure SQLiteCursor that are wrapped when returned
* to an Activity and therefore unreachable.
*/
@Override
public void close()
{
super.close();
if ( mDatabase != null )
{
mDatabase.close();
}
}
/**
* Closes cursor without closing database.
*/
public void closeForReuse()
{
super.close();
}
@Override
public String toString()
{
return super.toString() + ", ID# " + mID;
}
} // end of MyCursor class
//========================================================================
// Nested Class to create the MyCursor for queries
class MyCursorFactory implements SQLiteDatabase.CursorFactory
{
/**
* Creates and returns a new Cursor of MyCursor type.
*/
public Cursor newCursor ( SQLiteDatabase database,
SQLiteCursorDriver driver,
String editTable,
SQLiteQuery query )
{
int cursorID = MyProvider.CursorID++;
return new MyCursor(database,
driver,
editTable,
query,
cursorID);
}
} // end of MyCursorFactory class
Этот код предоставляет объект курсора, который закрывает базу данных, когда сам курсор закрыт, разрешая исключение IllegalStateException во время сборки мусора. Это накладывает ответственность за закрытие курсора на активность, которая его запросила. Это не должно создавать дополнительную нагрузку на действие, так как закрытие курсора, когда оно выполнено, является хорошей практикой.
Эти два класса вложены в MyProvider, мой класс контент-провайдера, и элемент данных CursorID инициализируется MyProvider.